From 43dc723813dc5e99baf17e0a3d61d47290f6349f Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Tue, 30 Jun 2020 16:05:44 +0900 Subject: [PATCH 001/694] Update documentation --- docs/concepts-guidelines.md | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/concepts-guidelines.md b/docs/concepts-guidelines.md index 358bd24..dc6f64b 100644 --- a/docs/concepts-guidelines.md +++ b/docs/concepts-guidelines.md @@ -15,6 +15,7 @@ This document covers terminology, how the action works, general usage guidelines - [Creating pull requests in a remote repository](#creating-pull-requests-in-a-remote-repository) - [Push using SSH (deploy keys)](#push-using-ssh-deploy-keys) - [Push pull request branches to a fork](#push-pull-request-branches-to-a-fork) + - [Authenticating with GitHub App generated tokens](#authenticating-with-github-app-generated-tokens) - [Running in a container](#running-in-a-container) - [Creating pull requests on tag push](#creating-pull-requests-on-tag-push) @@ -130,6 +131,7 @@ There are a number of workarounds with different pros and cons. - Use a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) created on an account that has write access to the repository that pull requests are being created in. This is the standard workaround and [recommended by GitHub](https://help.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token). However, the PAT cannot be scoped to a specific repository so the token becomes a very sensitive secret. If this is a concern, the PAT can instead be created for a dedicated [machine account](https://help.github.com/en/github/site-policy/github-terms-of-service#3-account-requirements) that has collaborator access to the repository. Also note that because the account that owns the PAT will be the creator of pull requests, that user account will be unable to perform actions such as request changes or approve the pull request. - Use [SSH (deploy keys)](#push-using-ssh-deploy-keys) to push the pull request branch. This is arguably more secure than using a PAT because deploy keys can be set per repository. However, this method will only trigger `on: push` workflows. - Use a [machine account that creates pull requests from its own fork](#push-pull-request-branches-to-a-fork). This is the most secure because the PAT created only grants access to the machine account's fork, not the main repository. This method will trigger `on: pull_request` workflows to run. Workflows triggered `on: push` will not run because the push event is in the fork. +- Use a [GitHub App to generate a token](#authenticating-with-github-app-generated-tokens) that can be used with this action. GitHub App generated tokens are slightly more secure than using a PAT because GitHub App access permissions can be set with finer granularity. This method will trigger both `on: push` and `on: pull_request` workflows. ### Security @@ -224,6 +226,44 @@ It will use their own fork to push code and create the pull request. request-to-parent: true ``` +### Authenticating with GitHub App generated tokens + +A GitHub App can be created for the sole purpose of generating tokens for use with GitHub actions. These tokens can be used in place of `GITHUB_TOKEN` or a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). + +1. Create a minimal [GitHub App](https://developer.github.com/apps/building-github-apps/creating-a-github-app/), setting the following fields: + + - Set `GitHub App name`. + - Set `Homepage URL` to anything you like, such as your GitHub profile page. + - Uncheck `Active` under `Webhook`. You do not need to enter a `Webhook URL`. + - Under `Repository permissions: Contents` select `Access: Read & write`. + - Under `Repository permissions: Pull requests` select `Access: Read & write`. + +2. Create a Private key from the App settings page and store it securely. + +3. Install the App on any repository where workflows will run requiring tokens. + +4. Set secrets on your repository containing the GitHub App ID, and the private key you created in step 2. e.g. `APP_ID`, `APP_PRIVATE_KEY`. + +5. The following example workflow shows how to use [tibdex/github-app-token](https://github.com/tibdex/github-app-token) to generate a token for use with this action. + +```yaml + steps: + - uses: actions/checkout@v2 + + - uses: tibdex/github-app-token@v1 + id: generate-token + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + + # Make changes to pull request here + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v2 + with: + token: ${{ steps.generate-token.outputs.token }} +``` + ### Running in a container This action can be run inside a container by installing the action's dependencies either in the Docker image itself, or during the workflow. From b7eabdce593cfe57cb1d33d308f2ca3bf255852c Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Tue, 30 Jun 2020 16:39:01 +0900 Subject: [PATCH 002/694] Update documentation --- docs/concepts-guidelines.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/concepts-guidelines.md b/docs/concepts-guidelines.md index dc6f64b..053bc8f 100644 --- a/docs/concepts-guidelines.md +++ b/docs/concepts-guidelines.md @@ -131,7 +131,7 @@ There are a number of workarounds with different pros and cons. - Use a `repo` scoped [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) created on an account that has write access to the repository that pull requests are being created in. This is the standard workaround and [recommended by GitHub](https://help.github.com/en/actions/reference/events-that-trigger-workflows#triggering-new-workflows-using-a-personal-access-token). However, the PAT cannot be scoped to a specific repository so the token becomes a very sensitive secret. If this is a concern, the PAT can instead be created for a dedicated [machine account](https://help.github.com/en/github/site-policy/github-terms-of-service#3-account-requirements) that has collaborator access to the repository. Also note that because the account that owns the PAT will be the creator of pull requests, that user account will be unable to perform actions such as request changes or approve the pull request. - Use [SSH (deploy keys)](#push-using-ssh-deploy-keys) to push the pull request branch. This is arguably more secure than using a PAT because deploy keys can be set per repository. However, this method will only trigger `on: push` workflows. - Use a [machine account that creates pull requests from its own fork](#push-pull-request-branches-to-a-fork). This is the most secure because the PAT created only grants access to the machine account's fork, not the main repository. This method will trigger `on: pull_request` workflows to run. Workflows triggered `on: push` will not run because the push event is in the fork. -- Use a [GitHub App to generate a token](#authenticating-with-github-app-generated-tokens) that can be used with this action. GitHub App generated tokens are slightly more secure than using a PAT because GitHub App access permissions can be set with finer granularity. This method will trigger both `on: push` and `on: pull_request` workflows. +- Use a [GitHub App to generate a token](#authenticating-with-github-app-generated-tokens) that can be used with this action. GitHub App generated tokens are more secure than using a PAT because GitHub App access permissions can be set with finer granularity and are scoped to only repositories where the App is installed. This method will trigger both `on: push` and `on: pull_request` workflows. ### Security @@ -228,7 +228,9 @@ It will use their own fork to push code and create the pull request. ### Authenticating with GitHub App generated tokens -A GitHub App can be created for the sole purpose of generating tokens for use with GitHub actions. These tokens can be used in place of `GITHUB_TOKEN` or a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). +A GitHub App can be created for the sole purpose of generating tokens for use with GitHub actions. +These tokens can be used in place of `GITHUB_TOKEN` or a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). +GitHub App generated tokens are more secure than using a PAT because GitHub App access permissions can be set with finer granularity and are scoped to only repositories where the App is installed. 1. Create a minimal [GitHub App](https://developer.github.com/apps/building-github-apps/creating-a-github-app/), setting the following fields: From 40e70b8f7b4f2b5c96d75987c33edeb013cb81ab Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Wed, 1 Jul 2020 09:42:27 +0900 Subject: [PATCH 003/694] Update documentation --- docs/concepts-guidelines.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/concepts-guidelines.md b/docs/concepts-guidelines.md index 053bc8f..acdd073 100644 --- a/docs/concepts-guidelines.md +++ b/docs/concepts-guidelines.md @@ -208,15 +208,17 @@ It will use their own fork to push code and create the pull request. 3. Create a [Personal Access Token (PAT)](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line). 4. Logout and log back in to your main user account. 5. Add a secret to your repository containing the above PAT. -6. As shown in the following example workflow, switch the git remote to the fork's URL after checkout and set the action input `request-to-parent` to `true`. +6. As shown in the following example workflow, switch the git remote to the fork's URL after checkout and update the fork to match the checked out branch. Then set the action input `request-to-parent` to `true`. ```yaml - uses: actions/checkout@v2 + with: + persist-credentials: false - run: | - git config user.password ${{ secrets.MACHINE_USER_PAT }} - git remote set-url origin https://github.com/machine-user/fork-of-repository + git remote set-url origin https://${{ secrets.MACHINE_USER_PAT }}:x-oauth-basic@github.com/machine-user/fork-of-repository git fetch --unshallow -p origin + git push --force # Make changes to pull request here From 4ba9ca3d1042787b3357fa72b60a6ccf267afaa0 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Thu, 16 Jul 2020 17:57:13 +0900 Subject: [PATCH 004/694] Convert action to typescript --- __test__/create-or-update-branch.int.test.ts | 951 ++ __test__/entrypoint.sh | 7 +- __test__/git-config-helper.int.test.ts | 117 + __test__/git.int.test.ts | 153 - __test__/git.unit.test.ts | 26 - __test__/utils.unit.test.ts | 116 + dist/index.js | 14036 ++++++++++++----- package-lock.json | 212 +- package.json | 6 +- src/create-or-update-branch.ts | 192 + src/create-pull-request.ts | 232 + src/git-command-manager.ts | 258 + src/git-config-helper.ts | 64 + src/git-identity-helper.ts | 105 + src/git.ts | 121 - src/github-helper.ts | 157 + src/main.ts | 116 +- src/octokit-client.ts | 7 + src/utils.ts | 107 + 19 files changed, 12517 insertions(+), 4466 deletions(-) create mode 100644 __test__/create-or-update-branch.int.test.ts create mode 100644 __test__/git-config-helper.int.test.ts delete mode 100644 __test__/git.int.test.ts delete mode 100644 __test__/git.unit.test.ts create mode 100644 __test__/utils.unit.test.ts create mode 100644 src/create-or-update-branch.ts create mode 100644 src/create-pull-request.ts create mode 100644 src/git-command-manager.ts create mode 100644 src/git-config-helper.ts create mode 100644 src/git-identity-helper.ts delete mode 100644 src/git.ts create mode 100644 src/github-helper.ts create mode 100644 src/octokit-client.ts create mode 100644 src/utils.ts diff --git a/__test__/create-or-update-branch.int.test.ts b/__test__/create-or-update-branch.int.test.ts new file mode 100644 index 0000000..3773d3e --- /dev/null +++ b/__test__/create-or-update-branch.int.test.ts @@ -0,0 +1,951 @@ +import {createOrUpdateBranch, tryFetch} from '../lib/create-or-update-branch' +import * as fs from 'fs' +import {GitCommandManager} from '../lib/git-command-manager' +import * as path from 'path' +import {v4 as uuidv4} from 'uuid' + +const REPO_PATH = '/git/test-repo' + +const TRACKED_FILE = 'tracked-file.txt' +const UNTRACKED_FILE = 'untracked-file.txt' + +const DEFAULT_BRANCH = 'tests/master' +const NOT_BASE_BRANCH = 'tests/branch-that-is-not-the-base' +const NOT_EXIST_BRANCH = 'tests/branch-that-does-not-exist' + +const INIT_COMMIT_MESSAGE = 'Add file to be a tracked file for tests' +const BRANCH = 'tests/create-pull-request/patch' +const BASE = DEFAULT_BRANCH + +async function createFile(filename: string, content?: string): Promise { + const _content = content ? content : uuidv4() + const filepath = path.join(REPO_PATH, filename) + await fs.promises.writeFile(filepath, _content, {encoding: 'utf8'}) + return _content +} + +async function getFileContent(filename: string): Promise { + const filepath = path.join(REPO_PATH, filename) + return await fs.promises.readFile(filepath, {encoding: 'utf8'}) +} + +interface ChangeContent { + tracked: string + untracked: string +} + +async function createChanges( + trackedContent?: string, + untrackedContent?: string +): Promise { + return { + tracked: await createFile(TRACKED_FILE, trackedContent), + untracked: await createFile(UNTRACKED_FILE, untrackedContent) + } +} + +interface Commits { + changes: ChangeContent + commitMsgs: string[] +} + +async function createCommits( + git: GitCommandManager, + number = 2, + finalTrackedContent?: string, + finalUntrackedContent?: string +): Promise { + let result: Commits = { + changes: {tracked: '', untracked: ''}, + commitMsgs: [] + } + for (let i = 1; i <= number; i++) { + if (i == number) { + result.changes = await createChanges( + finalTrackedContent, + finalUntrackedContent + ) + } else { + result.changes = await createChanges() + } + const commitMessage = uuidv4() + await git.exec(['add', '-A']) + await git.commit(['-m', commitMessage]) + result.commitMsgs.unshift(commitMessage) + } + return result +} + +describe('create-or-update-branch tests', () => { + let git: GitCommandManager + let initCommitHash: string + + beforeAll(async () => { + git = await GitCommandManager.create(REPO_PATH) + git.setAuthGitOptions([ + '-c', + 'http.https://github.com/.extraheader=AUTHORIZATION: basic xxx' + ]) + git.setIdentityGitOptions([ + '-c', + 'author.name=Author Name', + '-c', + 'author.email=author@example.com', + '-c', + 'committer.name=Committer Name', + '-c', + 'committer.email=committer@example.com' + ]) + // Check there are no local changes that might be destroyed by running these tests + expect(await git.isDirty(true)).toBeFalsy() + // Fetch the default branch + await git.fetch(['master:refs/remotes/origin/master']) + + // Create a "not base branch" for the test run + await git.checkout('master') + await git.checkout(NOT_BASE_BRANCH, 'HEAD') + await createFile(TRACKED_FILE) + await git.exec(['add', '-A']) + await git.commit(['-m', 'This commit should not appear in pr branches']) + await git.push(['--force', 'origin', `HEAD:refs/heads/${NOT_BASE_BRANCH}`]) + + // Create a new default branch for the test run with a tracked file + await git.checkout('master') + await git.checkout(DEFAULT_BRANCH, 'HEAD') + await createFile(TRACKED_FILE) + await git.exec(['add', '-A']) + await git.commit(['-m', INIT_COMMIT_MESSAGE]) + await git.push(['--force', 'origin', `HEAD:refs/heads/${DEFAULT_BRANCH}`]) + initCommitHash = await git.revParse('HEAD') + }) + + async function beforeTest(): Promise { + await git.checkout(DEFAULT_BRANCH) + } + + async function afterTest(deleteRemote = true): Promise { + //await git.exec(['log', '-5', '--format=%H %s']) + await git.checkout(DEFAULT_BRANCH) + // Delete PR branch + try { + await git.exec(['branch', '--delete', '--force', BRANCH]) + if (deleteRemote) { + await git.push([ + '--delete', + '--force', + 'origin', + `refs/heads/${BRANCH}` + ]) + } + } catch { + /* empty */ + } + } + + beforeEach(async () => { + await beforeTest() + }) + + afterEach(async () => { + await afterTest() + // Reset default branch if it was committed to during the test + if ((await git.revParse('HEAD')) != initCommitHash) { + await git.exec(['reset', '--hard', initCommitHash]) + await git.push(['--force', 'origin', `HEAD:refs/heads/${DEFAULT_BRANCH}`]) + } + }) + + async function gitLogMatches(expectedCommitMsgs: string[]): Promise { + const count = expectedCommitMsgs.length + const result = await git.exec(['log', `-${count}`, '--format=%s']) + const commitMsgs = result.stdout + .split('\n') + .map(s => s.trim()) + .filter(x => x !== '') + for (var index in expectedCommitMsgs) { + if (expectedCommitMsgs[index] != commitMsgs[index]) { + return false + } + } + return true + } + + it('tests if a branch exists and can be fetched', async () => { + expect(await tryFetch(git, NOT_BASE_BRANCH)).toBeTruthy() + expect(await tryFetch(git, NOT_EXIST_BRANCH)).toBeFalsy() + }) + + it('tests no changes resulting in no new branch being created', async () => { + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('none') + expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy() + }) + + it('tests create and update with a tracked file change', async () => { + // Create a tracked file change + const trackedContent = await createFile(TRACKED_FILE) + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(trackedContent) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create a tracked file change + const _trackedContent = await createFile(TRACKED_FILE) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_trackedContent) + expect( + await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with an untracked file change', async () => { + // Create an untracked file change + const untrackedContent = await createFile(UNTRACKED_FILE) + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(UNTRACKED_FILE)).toEqual(untrackedContent) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create an untracked file change + const _untrackedContent = await createFile(UNTRACKED_FILE) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_untrackedContent) + expect( + await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with identical changes', async () => { + // The pull request branch will not be updated + + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create identical tracked and untracked file changes + await createChanges(changes.tracked, changes.untracked) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('none') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with commits on the base inbetween', async () => { + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create commits on the base + const commits = await createCommits(git) + await git.push(['--force', 'origin', `HEAD:refs/heads/${DEFAULT_BRANCH}`]) + + // Create tracked and untracked file changes + const _changes = await createChanges() + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked) + expect( + await gitLogMatches([ + _commitMessage, + ...commits.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + }) + + it('tests create and then an update with no changes', async () => { + // This effectively reverts the branch back to match the base and results in no diff + + // Save the default branch tracked content + const defaultTrackedContent = await getFileContent(TRACKED_FILE) + + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Running with no update effectively reverts the branch back to match the base + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeFalsy() + expect(await getFileContent(TRACKED_FILE)).toEqual(defaultTrackedContent) + expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy() + }) + + it('tests create, commits on the base, and update with identical changes to the base', async () => { + // The changes on base effectively revert the branch back to match the base and results in no diff + + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create commits on the base + const commits = await createCommits(git) + await git.push(['--force', 'origin', `HEAD:refs/heads/${DEFAULT_BRANCH}`]) + + // Create the same tracked and untracked file changes that were made to the base + const _changes = await createChanges( + commits.changes.tracked, + commits.changes.untracked + ) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeFalsy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked) + expect( + await gitLogMatches([...commits.commitMsgs, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with commits on the working base (during the workflow)', async () => { + // Create commits on the working base + const commits = await createCommits(git) + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(commits.changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual( + commits.changes.untracked + ) + expect( + await gitLogMatches([...commits.commitMsgs, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create commits on the working base + const _commits = await createCommits(git) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_commits.changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual( + _commits.changes.untracked + ) + expect( + await gitLogMatches([..._commits.commitMsgs, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with changes and commits on the working base (during the workflow)', async () => { + // Create commits on the working base + const commits = await createCommits(git) + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([ + commitMessage, + ...commits.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create commits on the working base + const _commits = await createCommits(git) + // Create tracked and untracked file changes + const _changes = await createChanges() + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked) + expect( + await gitLogMatches([ + _commitMessage, + ..._commits.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + }) + + it('tests create and update with changes and commits on the working base (during the workflow), and commits on the base inbetween', async () => { + // Create commits on the working base + const commits = await createCommits(git) + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, '', BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([ + commitMessage, + ...commits.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create commits on the base + const commitsOnBase = await createCommits(git) + await git.push(['--force', 'origin', `HEAD:refs/heads/${DEFAULT_BRANCH}`]) + + // Create commits on the working base + const _commits = await createCommits(git) + // Create tracked and untracked file changes + const _changes = await createChanges() + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch(git, _commitMessage, '', BRANCH) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked) + expect( + await gitLogMatches([ + _commitMessage, + ..._commits.commitMsgs, + ...commitsOnBase.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + }) + + // Working Base is Not Base (WBNB) + + it('tests no changes resulting in no new branch being created (WBNB)', async () => { + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('none') + expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy() + }) + + it('tests create and update with a tracked file change (WBNB)', async () => { + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create a tracked file change + const trackedContent = await createFile(TRACKED_FILE) + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(trackedContent) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create a tracked file change + const _trackedContent = await createFile(TRACKED_FILE) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_trackedContent) + expect( + await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with an untracked file change (WBNB)', async () => { + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create an untracked file change + const untrackedContent = await createFile(UNTRACKED_FILE) + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(UNTRACKED_FILE)).toEqual(untrackedContent) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create an untracked file change + const _untrackedContent = await createFile(UNTRACKED_FILE) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_untrackedContent) + expect( + await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with identical changes (WBNB)', async () => { + // The pull request branch will not be updated + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create identical tracked and untracked file changes + await createChanges(changes.tracked, changes.untracked) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('none') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with commits on the base inbetween (WBNB)', async () => { + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create commits on the base + const commits = await createCommits(git) + await git.push(['--force', 'origin', `HEAD:refs/heads/${DEFAULT_BRANCH}`]) + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create tracked and untracked file changes + const _changes = await createChanges() + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked) + expect( + await gitLogMatches([ + _commitMessage, + ...commits.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + }) + + it('tests create and then an update with no changes (WBNB)', async () => { + // This effectively reverts the branch back to match the base and results in no diff + + // Save the default branch tracked content + const defaultTrackedContent = await getFileContent(TRACKED_FILE) + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Running with no update effectively reverts the branch back to match the base + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeFalsy() + expect(await getFileContent(TRACKED_FILE)).toEqual(defaultTrackedContent) + expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy() + }) + + it('tests create, commits on the base, and update with identical changes to the base (WBNB)', async () => { + // The changes on base effectively revert the branch back to match the base and results in no diff + // This scenario will cause cherrypick to fail due to an empty commit. + // The commit is empty because the changes now exist on the base. + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create commits on the base + const commits = await createCommits(git) + await git.push(['--force', 'origin', `HEAD:refs/heads/${DEFAULT_BRANCH}`]) + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create the same tracked and untracked file changes that were made to the base + const _changes = await createChanges( + commits.changes.tracked, + commits.changes.untracked + ) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeFalsy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked) + expect( + await gitLogMatches([...commits.commitMsgs, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with commits on the working base (during the workflow) (WBNB)', async () => { + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create commits on the working base + const commits = await createCommits(git) + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(commits.changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual( + commits.changes.untracked + ) + expect( + await gitLogMatches([...commits.commitMsgs, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create commits on the working base + const _commits = await createCommits(git) + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_commits.changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual( + _commits.changes.untracked + ) + expect( + await gitLogMatches([..._commits.commitMsgs, INIT_COMMIT_MESSAGE]) + ).toBeTruthy() + }) + + it('tests create and update with changes and commits on the working base (during the workflow) (WBNB)', async () => { + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create commits on the working base + const commits = await createCommits(git) + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([ + commitMessage, + ...commits.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create commits on the working base + const _commits = await createCommits(git) + // Create tracked and untracked file changes + const _changes = await createChanges() + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked) + expect( + await gitLogMatches([ + _commitMessage, + ..._commits.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + }) + + it('tests create and update with changes and commits on the working base (during the workflow), and commits on the base inbetween (WBNB)', async () => { + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create commits on the working base + const commits = await createCommits(git) + // Create tracked and untracked file changes + const changes = await createChanges() + const commitMessage = uuidv4() + const result = await createOrUpdateBranch(git, commitMessage, BASE, BRANCH) + expect(result.action).toEqual('created') + expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked) + expect( + await gitLogMatches([ + commitMessage, + ...commits.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + + // Push pull request branch to remote + await git.push(['--force', 'origin', `HEAD:refs/heads/${BRANCH}`]) + + await afterTest(false) + await beforeTest() + + // Create commits on the base + const commitsOnBase = await createCommits(git) + await git.push(['--force', 'origin', `HEAD:refs/heads/${DEFAULT_BRANCH}`]) + + // Set the working base to a branch that is not the pull request base + await git.checkout(NOT_BASE_BRANCH) + + // Create commits on the working base + const _commits = await createCommits(git) + // Create tracked and untracked file changes + const _changes = await createChanges() + const _commitMessage = uuidv4() + const _result = await createOrUpdateBranch( + git, + _commitMessage, + BASE, + BRANCH + ) + expect(_result.action).toEqual('updated') + expect(_result.hasDiffWithBase).toBeTruthy() + expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked) + expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked) + expect( + await gitLogMatches([ + _commitMessage, + ..._commits.commitMsgs, + ...commitsOnBase.commitMsgs, + INIT_COMMIT_MESSAGE + ]) + ).toBeTruthy() + }) +}) diff --git a/__test__/entrypoint.sh b/__test__/entrypoint.sh index a37ef21..1cd0560 100755 --- a/__test__/entrypoint.sh +++ b/__test__/entrypoint.sh @@ -21,9 +21,14 @@ echo "#test-repo" > README.md git add . git commit -m "initial commit" git push -u +git config --global --unset user.email +git config --global --unset user.name + +# Display config +git config -l # Restore the working directory cd $WORKINGDIR # Execute integration tests -jest int +jest int --runInBand diff --git a/__test__/git-config-helper.int.test.ts b/__test__/git-config-helper.int.test.ts new file mode 100644 index 0000000..4ff160b --- /dev/null +++ b/__test__/git-config-helper.int.test.ts @@ -0,0 +1,117 @@ +import {GitCommandManager} from '../lib/git-command-manager' +import {GitConfigHelper} from '../lib/git-config-helper' + +const REPO_PATH = '/git/test-repo' + +describe('git-config-helper tests', () => { + let gitConfigHelper: GitConfigHelper + + beforeAll(async () => { + const git = await GitCommandManager.create(REPO_PATH) + gitConfigHelper = new GitConfigHelper(git) + }) + + it('adds and unsets a config option', async () => { + const add = await gitConfigHelper.addConfigOption( + 'test.add.and.unset.config.option', + 'foo' + ) + expect(add).toBeTruthy() + const unset = await gitConfigHelper.unsetConfigOption( + 'test.add.and.unset.config.option' + ) + expect(unset).toBeTruthy() + }) + + it('adds and unsets a config option with value regex', async () => { + const add = await gitConfigHelper.addConfigOption( + 'test.add.and.unset.config.option', + 'foo bar' + ) + expect(add).toBeTruthy() + const unset = await gitConfigHelper.unsetConfigOption( + 'test.add.and.unset.config.option', + '^foo' + ) + expect(unset).toBeTruthy() + }) + + it('determines that a config option exists', async () => { + const result = await gitConfigHelper.configOptionExists('remote.origin.url') + expect(result).toBeTruthy() + }) + + it('determines that a config option does not exist', async () => { + const result = await gitConfigHelper.configOptionExists( + 'this.key.does.not.exist' + ) + expect(result).toBeFalsy() + }) + + it('successfully retrieves a config option', async () => { + const add = await gitConfigHelper.addConfigOption( + 'test.get.config.option', + 'foo' + ) + expect(add).toBeTruthy() + const option = await gitConfigHelper.getConfigOption( + 'test.get.config.option' + ) + expect(option.value).toEqual('foo') + const unset = await gitConfigHelper.unsetConfigOption( + 'test.get.config.option' + ) + expect(unset).toBeTruthy() + }) + + it('gets a config option with value regex', async () => { + const add = await gitConfigHelper.addConfigOption( + 'test.get.config.option', + 'foo bar' + ) + expect(add).toBeTruthy() + const option = await gitConfigHelper.getConfigOption( + 'test.get.config.option', + '^foo' + ) + expect(option.value).toEqual('foo bar') + const unset = await gitConfigHelper.unsetConfigOption( + 'test.get.config.option', + '^foo' + ) + expect(unset).toBeTruthy() + }) + + it('gets and unsets a config option', async () => { + const add = await gitConfigHelper.addConfigOption( + 'test.get.and.unset.config.option', + 'foo' + ) + expect(add).toBeTruthy() + const getAndUnset = await gitConfigHelper.getAndUnsetConfigOption( + 'test.get.and.unset.config.option' + ) + expect(getAndUnset.value).toEqual('foo') + }) + + it('gets and unsets a config option with value regex', async () => { + const add = await gitConfigHelper.addConfigOption( + 'test.get.and.unset.config.option', + 'foo bar' + ) + expect(add).toBeTruthy() + const getAndUnset = await gitConfigHelper.getAndUnsetConfigOption( + 'test.get.and.unset.config.option', + '^foo' + ) + expect(getAndUnset.value).toEqual('foo bar') + }) + + it('fails to get and unset a config option', async () => { + const getAndUnset = await gitConfigHelper.getAndUnsetConfigOption( + 'this.key.does.not.exist' + ) + expect(getAndUnset.name).toEqual('') + expect(getAndUnset.value).toEqual('') + }) +}) diff --git a/__test__/git.int.test.ts b/__test__/git.int.test.ts deleted file mode 100644 index 8c3b2a0..0000000 --- a/__test__/git.int.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { - getRepoPath, - execGit, - addConfigOption, - unsetConfigOption, - configOptionExists, - getConfigOption, - getAndUnsetConfigOption -} from '../lib/git' - -const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE'] - -describe('git tests', () => { - beforeAll(() => { - // GitHub workspace - process.env['GITHUB_WORKSPACE'] = '/git/test-repo' - }) - - afterAll(() => { - // Restore GitHub workspace - delete process.env['GITHUB_WORKSPACE'] - if (originalGitHubWorkspace) { - process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace - } - }) - - it('successfully executes a git command', async () => { - const repoPath = getRepoPath() - const result = await execGit( - repoPath, - ['config', '--local', '--name-only', '--get-regexp', 'remote.origin.url'], - true - ) - expect(result.exitCode).toEqual(0) - expect(result.stdout.trim()).toEqual('remote.origin.url') - }) - - it('adds and unsets a config option', async () => { - const repoPath = getRepoPath() - const add = await addConfigOption( - repoPath, - 'test.add.and.unset.config.option', - 'foo' - ) - expect(add).toBeTruthy() - const unset = await unsetConfigOption( - repoPath, - 'test.add.and.unset.config.option' - ) - expect(unset).toBeTruthy() - }) - - it('adds and unsets a config option with value regex', async () => { - const repoPath = getRepoPath() - const add = await addConfigOption( - repoPath, - 'test.add.and.unset.config.option', - 'foo bar' - ) - expect(add).toBeTruthy() - const unset = await unsetConfigOption( - repoPath, - 'test.add.and.unset.config.option', - '^foo' - ) - expect(unset).toBeTruthy() - }) - - it('determines that a config option exists', async () => { - const repoPath = getRepoPath() - const result = await configOptionExists(repoPath, 'remote.origin.url') - expect(result).toBeTruthy() - }) - - it('determines that a config option does not exist', async () => { - const repoPath = getRepoPath() - const result = await configOptionExists(repoPath, 'this.key.does.not.exist') - expect(result).toBeFalsy() - }) - - it('successfully retrieves a config option', async () => { - const repoPath = getRepoPath() - const add = await addConfigOption(repoPath, 'test.get.config.option', 'foo') - expect(add).toBeTruthy() - const option = await getConfigOption(repoPath, 'test.get.config.option') - expect(option.value).toEqual('foo') - const unset = await unsetConfigOption(repoPath, 'test.get.config.option') - expect(unset).toBeTruthy() - }) - - it('gets a config option with value regex', async () => { - const repoPath = getRepoPath() - const add = await addConfigOption( - repoPath, - 'test.get.config.option', - 'foo bar' - ) - expect(add).toBeTruthy() - const option = await getConfigOption( - repoPath, - 'test.get.config.option', - '^foo' - ) - expect(option.value).toEqual('foo bar') - const unset = await unsetConfigOption( - repoPath, - 'test.get.config.option', - '^foo' - ) - expect(unset).toBeTruthy() - }) - - it('gets and unsets a config option', async () => { - const repoPath = getRepoPath() - const add = await addConfigOption( - repoPath, - 'test.get.and.unset.config.option', - 'foo' - ) - expect(add).toBeTruthy() - const getAndUnset = await getAndUnsetConfigOption( - repoPath, - 'test.get.and.unset.config.option' - ) - expect(getAndUnset.value).toEqual('foo') - }) - - it('gets and unsets a config option with value regex', async () => { - const repoPath = getRepoPath() - const add = await addConfigOption( - repoPath, - 'test.get.and.unset.config.option', - 'foo bar' - ) - expect(add).toBeTruthy() - const getAndUnset = await getAndUnsetConfigOption( - repoPath, - 'test.get.and.unset.config.option', - '^foo' - ) - expect(getAndUnset.value).toEqual('foo bar') - }) - - it('fails to get and unset a config option', async () => { - const repoPath = getRepoPath() - const getAndUnset = await getAndUnsetConfigOption( - repoPath, - 'this.key.does.not.exist' - ) - expect(getAndUnset.name).toEqual('') - expect(getAndUnset.value).toEqual('') - }) -}) diff --git a/__test__/git.unit.test.ts b/__test__/git.unit.test.ts deleted file mode 100644 index adf0448..0000000 --- a/__test__/git.unit.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import * as path from 'path' -import {getRepoPath} from '../lib/git' - -const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE'] - -describe('git tests', () => { - beforeAll(() => { - // GitHub workspace - process.env['GITHUB_WORKSPACE'] = __dirname - }) - - afterAll(() => { - // Restore GitHub workspace - delete process.env['GITHUB_WORKSPACE'] - if (originalGitHubWorkspace) { - process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace - } - }) - - test('getRepoPath', async () => { - expect(getRepoPath()).toEqual(process.env['GITHUB_WORKSPACE']) - expect(getRepoPath('foo')).toEqual( - path.resolve(process.env['GITHUB_WORKSPACE'] || '', 'foo') - ) - }) -}) diff --git a/__test__/utils.unit.test.ts b/__test__/utils.unit.test.ts new file mode 100644 index 0000000..1c2f0a9 --- /dev/null +++ b/__test__/utils.unit.test.ts @@ -0,0 +1,116 @@ +import * as path from 'path' +import * as utils from '../lib/utils' + +const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE'] + +describe('utils tests', () => { + beforeAll(() => { + // GitHub workspace + process.env['GITHUB_WORKSPACE'] = __dirname + }) + + afterAll(() => { + // Restore GitHub workspace + delete process.env['GITHUB_WORKSPACE'] + if (originalGitHubWorkspace) { + process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace + } + }) + + test('getStringAsArray splits string input by newlines and commas', async () => { + const array = utils.getStringAsArray('1, 2, 3\n4, 5, 6') + expect(array.length).toEqual(6) + + const array2 = utils.getStringAsArray('') + expect(array2.length).toEqual(0) + }) + + test('getRepoPath successfully returns the path to the repository', async () => { + expect(utils.getRepoPath()).toEqual(process.env['GITHUB_WORKSPACE']) + expect(utils.getRepoPath('foo')).toEqual( + path.resolve(process.env['GITHUB_WORKSPACE'] || '', 'foo') + ) + }) + + test('getRemoteDetail successfully parses remote URLs', async () => { + const remote1 = utils.getRemoteDetail( + 'https://github.com/peter-evans/create-pull-request' + ) + expect(remote1.protocol).toEqual('HTTPS') + expect(remote1.repository).toEqual('peter-evans/create-pull-request') + + const remote2 = utils.getRemoteDetail( + 'https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request' + ) + expect(remote2.protocol).toEqual('HTTPS') + expect(remote2.repository).toEqual('peter-evans/create-pull-request') + + const remote3 = utils.getRemoteDetail( + 'git@github.com:peter-evans/create-pull-request.git' + ) + expect(remote3.protocol).toEqual('SSH') + expect(remote3.repository).toEqual('peter-evans/create-pull-request') + }) + + test('getRemoteDetail fails to parse a remote URL', async () => { + const remoteUrl = 'https://github.com/peter-evans' + try { + utils.getRemoteDetail(remoteUrl) + // Fail the test if an error wasn't thrown + expect(true).toEqual(false) + } catch (e) { + expect(e.message).toEqual( + `The format of '${remoteUrl}' is not a valid GitHub repository URL` + ) + } + }) + + test('secondsSinceEpoch returns the number of seconds since the Epoch', async () => { + const seconds = `${utils.secondsSinceEpoch()}` + expect(seconds.length).toEqual(10) + }) + + test('randomString returns strings of length 7', async () => { + for (let i = 0; i < 1000; i++) { + expect(utils.randomString().length).toEqual(7) + } + }) + + test('parseDisplayNameEmail successfully parses display name email formats', async () => { + const parsed1 = utils.parseDisplayNameEmail('abc def ') + expect(parsed1.name).toEqual('abc def') + expect(parsed1.email).toEqual('abc@def.com') + + const parsed2 = utils.parseDisplayNameEmail( + 'github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>' + ) + expect(parsed2.name).toEqual('github-actions[bot]') + expect(parsed2.email).toEqual( + '41898282+github-actions[bot]@users.noreply.github.com' + ) + }) + + test('parseDisplayNameEmail fails to parse display name email formats', async () => { + const displayNameEmail1 = 'abc@def.com' + try { + utils.parseDisplayNameEmail(displayNameEmail1) + // Fail the test if an error wasn't thrown + expect(true).toEqual(false) + } catch (e) { + expect(e.message).toEqual( + `The format of '${displayNameEmail1}' is not a valid email address with display name` + ) + } + + const displayNameEmail2 = ' < >' + try { + utils.parseDisplayNameEmail(displayNameEmail2) + // Fail the test if an error wasn't thrown + expect(true).toEqual(false) + } catch (e) { + expect(e.message).toEqual( + `The format of '${displayNameEmail2}' is not a valid email address with display name` + ) + } + }) +}) diff --git a/dist/index.js b/dist/index.js index 73bb52e..53cbf48 100644 --- a/dist/index.js +++ b/dist/index.js @@ -338,9 +338,7009 @@ function copyFile(srcFile, destFile, force) { } //# sourceMappingURL=io.js.map +/***/ }), + +/***/ 2: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const os = __webpack_require__(87); +const macosRelease = __webpack_require__(118); +const winRelease = __webpack_require__(49); + +const osName = (platform, release) => { + if (!platform && release) { + throw new Error('You can\'t specify a `release` without specifying `platform`'); + } + + platform = platform || os.platform(); + + let id; + + if (platform === 'darwin') { + if (!release && os.platform() === 'darwin') { + release = os.release(); + } + + const prefix = release ? (Number(release.split('.')[0]) > 15 ? 'macOS' : 'OS X') : 'macOS'; + id = release ? macosRelease(release).name : ''; + return prefix + (id ? ' ' + id : ''); + } + + if (platform === 'linux') { + if (!release && os.platform() === 'linux') { + release = os.release(); + } + + id = release ? release.replace(/^(\d+\.\d+).*/, '$1') : ''; + return 'Linux' + (id ? ' ' + id : ''); + } + + if (platform === 'win32') { + if (!release && os.platform() === 'win32') { + release = os.release(); + } + + id = release ? winRelease(release) : ''; + return 'Windows' + (id ? ' ' + id : ''); + } + + return platform; +}; + +module.exports = osName; + + /***/ }), /***/ 9: +/***/ (function(module, __unusedexports, __webpack_require__) { + +var once = __webpack_require__(969); + +var noop = function() {}; + +var isRequest = function(stream) { + return stream.setHeader && typeof stream.abort === 'function'; +}; + +var isChildProcess = function(stream) { + return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3 +}; + +var eos = function(stream, opts, callback) { + if (typeof opts === 'function') return eos(stream, null, opts); + if (!opts) opts = {}; + + callback = once(callback || noop); + + var ws = stream._writableState; + var rs = stream._readableState; + var readable = opts.readable || (opts.readable !== false && stream.readable); + var writable = opts.writable || (opts.writable !== false && stream.writable); + var cancelled = false; + + var onlegacyfinish = function() { + if (!stream.writable) onfinish(); + }; + + var onfinish = function() { + writable = false; + if (!readable) callback.call(stream); + }; + + var onend = function() { + readable = false; + if (!writable) callback.call(stream); + }; + + var onexit = function(exitCode) { + callback.call(stream, exitCode ? new Error('exited with error code: ' + exitCode) : null); + }; + + var onerror = function(err) { + callback.call(stream, err); + }; + + var onclose = function() { + process.nextTick(onclosenexttick); + }; + + var onclosenexttick = function() { + if (cancelled) return; + if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error('premature close')); + if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error('premature close')); + }; + + var onrequest = function() { + stream.req.on('finish', onfinish); + }; + + if (isRequest(stream)) { + stream.on('complete', onfinish); + stream.on('abort', onclose); + if (stream.req) onrequest(); + else stream.on('request', onrequest); + } else if (writable && !ws) { // legacy streams + stream.on('end', onlegacyfinish); + stream.on('close', onlegacyfinish); + } + + if (isChildProcess(stream)) stream.on('exit', onexit); + + stream.on('end', onend); + stream.on('finish', onfinish); + if (opts.error !== false) stream.on('error', onerror); + stream.on('close', onclose); + + return function() { + cancelled = true; + stream.removeListener('complete', onfinish); + stream.removeListener('abort', onclose); + stream.removeListener('request', onrequest); + if (stream.req) stream.req.removeListener('finish', onfinish); + stream.removeListener('end', onlegacyfinish); + stream.removeListener('close', onlegacyfinish); + stream.removeListener('finish', onfinish); + stream.removeListener('exit', onexit); + stream.removeListener('end', onend); + stream.removeListener('error', onerror); + stream.removeListener('close', onclose); + }; +}; + +module.exports = eos; + + +/***/ }), + +/***/ 11: +/***/ (function(module) { + +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} + + +/***/ }), + +/***/ 15: +/***/ (function(module) { + +"use strict"; + + +const isWin = process.platform === 'win32'; + +function notFoundError(original, syscall) { + return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), { + code: 'ENOENT', + errno: 'ENOENT', + syscall: `${syscall} ${original.command}`, + path: original.command, + spawnargs: original.args, + }); +} + +function hookChildProcess(cp, parsed) { + if (!isWin) { + return; + } + + const originalEmit = cp.emit; + + cp.emit = function (name, arg1) { + // If emitting "exit" event and exit code is 1, we need to check if + // the command exists and emit an "error" instead + // See https://github.com/IndigoUnited/node-cross-spawn/issues/16 + if (name === 'exit') { + const err = verifyENOENT(arg1, parsed, 'spawn'); + + if (err) { + return originalEmit.call(cp, 'error', err); + } + } + + return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params + }; +} + +function verifyENOENT(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawn'); + } + + return null; +} + +function verifyENOENTSync(status, parsed) { + if (isWin && status === 1 && !parsed.file) { + return notFoundError(parsed.original, 'spawnSync'); + } + + return null; +} + +module.exports = { + hookChildProcess, + verifyENOENT, + verifyENOENTSync, + notFoundError, +}; + + +/***/ }), + +/***/ 18: +/***/ (function(module) { + +module.exports = eval("require")("encoding"); + + +/***/ }), + +/***/ 49: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const os = __webpack_require__(87); +const execa = __webpack_require__(955); + +// Reference: https://www.gaijin.at/en/lstwinver.php +const names = new Map([ + ['10.0', '10'], + ['6.3', '8.1'], + ['6.2', '8'], + ['6.1', '7'], + ['6.0', 'Vista'], + ['5.2', 'Server 2003'], + ['5.1', 'XP'], + ['5.0', '2000'], + ['4.9', 'ME'], + ['4.1', '98'], + ['4.0', '95'] +]); + +const windowsRelease = release => { + const version = /\d+\.\d/.exec(release || os.release()); + + if (release && !version) { + throw new Error('`release` argument doesn\'t match `n.n`'); + } + + const ver = (version || [])[0]; + + // Server 2008, 2012, 2016, and 2019 versions are ambiguous with desktop versions and must be detected at runtime. + // If `release` is omitted or we're on a Windows system, and the version number is an ambiguous version + // then use `wmic` to get the OS caption: https://msdn.microsoft.com/en-us/library/aa394531(v=vs.85).aspx + // If `wmic` is obsoloete (later versions of Windows 10), use PowerShell instead. + // If the resulting caption contains the year 2008, 2012, 2016 or 2019, it is a server version, so return a server OS name. + if ((!release || release === os.release()) && ['6.1', '6.2', '6.3', '10.0'].includes(ver)) { + let stdout; + try { + stdout = execa.sync('wmic', ['os', 'get', 'Caption']).stdout || ''; + } catch (_) { + stdout = execa.sync('powershell', ['(Get-CimInstance -ClassName Win32_OperatingSystem).caption']).stdout || ''; + } + + const year = (stdout.match(/2008|2012|2016|2019/) || [])[0]; + + if (year) { + return `Server ${year}`; + } + } + + return names.get(ver); +}; + +module.exports = windowsRelease; + + +/***/ }), + +/***/ 55: +/***/ (function(module, __unusedexports, __webpack_require__) { + +module.exports = which +which.sync = whichSync + +var isWindows = process.platform === 'win32' || + process.env.OSTYPE === 'cygwin' || + process.env.OSTYPE === 'msys' + +var path = __webpack_require__(622) +var COLON = isWindows ? ';' : ':' +var isexe = __webpack_require__(742) + +function getNotFoundError (cmd) { + var er = new Error('not found: ' + cmd) + er.code = 'ENOENT' + + return er +} + +function getPathInfo (cmd, opt) { + var colon = opt.colon || COLON + var pathEnv = opt.path || process.env.PATH || '' + var pathExt = [''] + + pathEnv = pathEnv.split(colon) + + var pathExtExe = '' + if (isWindows) { + pathEnv.unshift(process.cwd()) + pathExtExe = (opt.pathExt || process.env.PATHEXT || '.EXE;.CMD;.BAT;.COM') + pathExt = pathExtExe.split(colon) + + + // Always test the cmd itself first. isexe will check to make sure + // it's found in the pathExt set. + if (cmd.indexOf('.') !== -1 && pathExt[0] !== '') + pathExt.unshift('') + } + + // If it has a slash, then we don't bother searching the pathenv. + // just check the file itself, and that's it. + if (cmd.match(/\//) || isWindows && cmd.match(/\\/)) + pathEnv = [''] + + return { + env: pathEnv, + ext: pathExt, + extExe: pathExtExe + } +} + +function which (cmd, opt, cb) { + if (typeof opt === 'function') { + cb = opt + opt = {} + } + + var info = getPathInfo(cmd, opt) + var pathEnv = info.env + var pathExt = info.ext + var pathExtExe = info.extExe + var found = [] + + ;(function F (i, l) { + if (i === l) { + if (opt.all && found.length) + return cb(null, found) + else + return cb(getNotFoundError(cmd)) + } + + var pathPart = pathEnv[i] + if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') + pathPart = pathPart.slice(1, -1) + + var p = path.join(pathPart, cmd) + if (!pathPart && (/^\.[\\\/]/).test(cmd)) { + p = cmd.slice(0, 2) + p + } + ;(function E (ii, ll) { + if (ii === ll) return F(i + 1, l) + var ext = pathExt[ii] + isexe(p + ext, { pathExt: pathExtExe }, function (er, is) { + if (!er && is) { + if (opt.all) + found.push(p + ext) + else + return cb(null, p + ext) + } + return E(ii + 1, ll) + }) + })(0, pathExt.length) + })(0, pathEnv.length) +} + +function whichSync (cmd, opt) { + opt = opt || {} + + var info = getPathInfo(cmd, opt) + var pathEnv = info.env + var pathExt = info.ext + var pathExtExe = info.extExe + var found = [] + + for (var i = 0, l = pathEnv.length; i < l; i ++) { + var pathPart = pathEnv[i] + if (pathPart.charAt(0) === '"' && pathPart.slice(-1) === '"') + pathPart = pathPart.slice(1, -1) + + var p = path.join(pathPart, cmd) + if (!pathPart && /^\.[\\\/]/.test(cmd)) { + p = cmd.slice(0, 2) + p + } + for (var j = 0, ll = pathExt.length; j < ll; j ++) { + var cur = p + pathExt[j] + var is + try { + is = isexe.sync(cur, { pathExt: pathExtExe }) + if (is) { + if (opt.all) + found.push(cur) + else + return cur + } + } catch (ex) {} + } + } + + if (opt.all && found.length) + return found + + if (opt.nothrow) + return null + + throw getNotFoundError(cmd) +} + + +/***/ }), + +/***/ 62: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "v1", { + enumerable: true, + get: function () { + return _v.default; + } +}); +Object.defineProperty(exports, "v3", { + enumerable: true, + get: function () { + return _v2.default; + } +}); +Object.defineProperty(exports, "v4", { + enumerable: true, + get: function () { + return _v3.default; + } +}); +Object.defineProperty(exports, "v5", { + enumerable: true, + get: function () { + return _v4.default; + } +}); + +var _v = _interopRequireDefault(__webpack_require__(893)); + +var _v2 = _interopRequireDefault(__webpack_require__(209)); + +var _v3 = _interopRequireDefault(__webpack_require__(733)); + +var _v4 = _interopRequireDefault(__webpack_require__(384)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 87: +/***/ (function(module) { + +module.exports = require("os"); + +/***/ }), + +/***/ 118: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const os = __webpack_require__(87); + +const nameMap = new Map([ + [20, ['Big Sur', '11']], + [19, ['Catalina', '10.15']], + [18, ['Mojave', '10.14']], + [17, ['High Sierra', '10.13']], + [16, ['Sierra', '10.12']], + [15, ['El Capitan', '10.11']], + [14, ['Yosemite', '10.10']], + [13, ['Mavericks', '10.9']], + [12, ['Mountain Lion', '10.8']], + [11, ['Lion', '10.7']], + [10, ['Snow Leopard', '10.6']], + [9, ['Leopard', '10.5']], + [8, ['Tiger', '10.4']], + [7, ['Panther', '10.3']], + [6, ['Jaguar', '10.2']], + [5, ['Puma', '10.1']] +]); + +const macosRelease = release => { + release = Number((release || os.release()).split('.')[0]); + + const [name, version] = nameMap.get(release); + + return { + name, + version + }; +}; + +module.exports = macosRelease; +// TODO: remove this in the next major version +module.exports.default = macosRelease; + + +/***/ }), + +/***/ 129: +/***/ (function(module) { + +module.exports = require("child_process"); + +/***/ }), + +/***/ 145: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const pump = __webpack_require__(453); +const bufferStream = __webpack_require__(966); + +class MaxBufferError extends Error { + constructor() { + super('maxBuffer exceeded'); + this.name = 'MaxBufferError'; + } +} + +function getStream(inputStream, options) { + if (!inputStream) { + return Promise.reject(new Error('Expected a stream')); + } + + options = Object.assign({maxBuffer: Infinity}, options); + + const {maxBuffer} = options; + + let stream; + return new Promise((resolve, reject) => { + const rejectPromise = error => { + if (error) { // A null check + error.bufferedData = stream.getBufferedValue(); + } + reject(error); + }; + + stream = pump(inputStream, bufferStream(options), error => { + if (error) { + rejectPromise(error); + return; + } + + resolve(); + }); + + stream.on('data', () => { + if (stream.getBufferedLength() > maxBuffer) { + rejectPromise(new MaxBufferError()); + } + }); + }).then(() => stream.getBufferedValue()); +} + +module.exports = getStream; +module.exports.buffer = (stream, options) => getStream(stream, Object.assign({}, options, {encoding: 'buffer'})); +module.exports.array = (stream, options) => getStream(stream, Object.assign({}, options, {array: true})); +module.exports.MaxBufferError = MaxBufferError; + + +/***/ }), + +/***/ 159: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createOrUpdateBranch = exports.tryFetch = void 0; +const core = __importStar(__webpack_require__(470)); +const uuid_1 = __webpack_require__(62); +const CHERRYPICK_EMPTY = 'The previous cherry-pick is now empty, possibly due to conflict resolution.'; +function tryFetch(git, branch) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield git.fetch([`${branch}:refs/remotes/origin/${branch}`]); + return true; + } + catch (_a) { + return false; + } + }); +} +exports.tryFetch = tryFetch; +// Return true if branch2 is ahead of branch1 +function isAhead(git, branch1, branch2) { + return __awaiter(this, void 0, void 0, function* () { + const result = yield git.revList([`${branch1}...${branch2}`], ['--right-only', '--count']); + return Number(result) > 0; + }); +} +// Return true if branch2 is behind branch1 +function isBehind(git, branch1, branch2) { + return __awaiter(this, void 0, void 0, function* () { + const result = yield git.revList([`${branch1}...${branch2}`], ['--left-only', '--count']); + return Number(result) > 0; + }); +} +// Return true if branch2 is even with branch1 +function isEven(git, branch1, branch2) { + return __awaiter(this, void 0, void 0, function* () { + return (!(yield isAhead(git, branch1, branch2)) && + !(yield isBehind(git, branch1, branch2))); + }); +} +function hasDiff(git, branch1, branch2) { + return __awaiter(this, void 0, void 0, function* () { + const result = yield git.diff([`${branch1}..${branch2}`]); + return result.length > 0; + }); +} +function splitLines(multilineString) { + return multilineString + .split('\n') + .map(s => s.trim()) + .filter(x => x !== ''); +} +function createOrUpdateBranch(git, commitMessage, baseInput, branch) { + return __awaiter(this, void 0, void 0, function* () { + // Get the working base. This may or may not be the actual base. + const workingBase = yield git.symbolicRef('HEAD', ['--short']); + // If the base is not specified it is assumed to be the working base. + const base = baseInput ? baseInput : workingBase; + // Set the default return values + const result = { + action: 'none', + base: base, + hasDiffWithBase: false + }; + // Save the working base changes to a temporary branch + const tempBranch = uuid_1.v4(); + yield git.checkout(tempBranch, 'HEAD'); + // Commit any uncomitted changes + if (yield git.isDirty(true)) { + core.info('Uncommitted changes found. Adding a commit.'); + yield git.exec(['add', '-A']); + yield git.commit(['-m', commitMessage]); + } + // Perform fetch and reset the working base + // Commits made during the workflow will be removed + yield git.fetch([`${workingBase}:${workingBase}`], 'origin', ['--force']); + // If the working base is not the base, rebase the temp branch commits + if (workingBase != base) { + core.info(`Rebasing commits made to branch '${workingBase}' on to base branch '${base}'`); + // Checkout the actual base + yield git.fetch([`${base}:${base}`], 'origin', ['--force']); + yield git.checkout(base); + // Cherrypick commits from the temporary branch starting from the working base + const commits = yield git.revList([`${workingBase}..${tempBranch}`, '.'], ['--reverse']); + for (const commit of splitLines(commits)) { + const result = yield git.cherryPick(['--strategy=recursive', '--strategy-option=theirs', commit], true); + if (result.exitCode != 0 && !result.stderr.includes(CHERRYPICK_EMPTY)) { + throw new Error(`Unexpected error: ${result.stderr}`); + } + } + // Reset the temp branch to the working index + yield git.checkout(tempBranch, 'HEAD'); + // Reset the base + yield git.fetch([`${base}:${base}`], 'origin', ['--force']); + } + // Try to fetch the pull request branch + if (!(yield tryFetch(git, branch))) { + // The pull request branch does not exist + core.info(`Pull request branch '${branch}' does not exist yet.`); + // Create the pull request branch + yield git.checkout(branch, 'HEAD'); + // Check if the pull request branch is ahead of the base + result.hasDiffWithBase = yield isAhead(git, base, branch); + if (result.hasDiffWithBase) { + result.action = 'created'; + core.info(`Created branch '${branch}'`); + } + else { + core.info(`Branch '${branch}' is not ahead of base '${base}' and will not be created`); + } + } + else { + // The pull request branch exists + core.info(`Pull request branch '${branch}' already exists as remote branch 'origin/${branch}'`); + // Checkout the pull request branch + yield git.checkout(branch); + if (yield hasDiff(git, branch, tempBranch)) { + // If the branch differs from the recreated temp version then the branch is reset + // For changes on base this action is similar to a rebase of the pull request branch + core.info(`Resetting '${branch}'`); + // Alternatively, git switch -C branch tempBranch + yield git.checkout(branch, tempBranch); + } + // Check if the pull request branch has been updated + // If the branch was reset or updated it will be ahead + // It may be behind if a reset now results in no diff with the base + if (!(yield isEven(git, `origin/${branch}`, branch))) { + result.action = 'updated'; + core.info(`Updated branch '${branch}'`); + } + else { + core.info(`Branch '${branch}' is even with its remote and will not be updated`); + } + // Check if the pull request branch is ahead of the base + result.hasDiffWithBase = yield isAhead(git, base, branch); + } + // Delete the temporary branch + yield git.exec(['branch', '--delete', '--force', tempBranch]); + return result; + }); +} +exports.createOrUpdateBranch = createOrUpdateBranch; + + +/***/ }), + +/***/ 168: +/***/ (function(module) { + +"use strict"; + +const alias = ['stdin', 'stdout', 'stderr']; + +const hasAlias = opts => alias.some(x => Boolean(opts[x])); + +module.exports = opts => { + if (!opts) { + return null; + } + + if (opts.stdio && hasAlias(opts)) { + throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${alias.map(x => `\`${x}\``).join(', ')}`); + } + + if (typeof opts.stdio === 'string') { + return opts.stdio; + } + + const stdio = opts.stdio || []; + + if (!Array.isArray(stdio)) { + throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``); + } + + const result = []; + const len = Math.max(stdio.length, alias.length); + + for (let i = 0; i < len; i++) { + let value = null; + + if (stdio[i] !== undefined) { + value = stdio[i]; + } else if (opts[alias[i]] !== undefined) { + value = opts[alias[i]]; + } + + result[i] = value; + } + + return result; +}; + + +/***/ }), + +/***/ 197: +/***/ (function(module, __unusedexports, __webpack_require__) { + +module.exports = isexe +isexe.sync = sync + +var fs = __webpack_require__(747) + +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, options)) + }) +} + +function sync (path, options) { + return checkStat(fs.statSync(path), options) +} + +function checkStat (stat, options) { + return stat.isFile() && checkMode(stat, options) +} + +function checkMode (stat, options) { + var mod = stat.mode + var uid = stat.uid + var gid = stat.gid + + var myUid = options.uid !== undefined ? + options.uid : process.getuid && process.getuid() + var myGid = options.gid !== undefined ? + options.gid : process.getgid && process.getgid() + + var u = parseInt('100', 8) + var g = parseInt('010', 8) + var o = parseInt('001', 8) + var ug = u | g + + var ret = (mod & o) || + (mod & g) && gid === myGid || + (mod & u) && uid === myUid || + (mod & ug) && myUid === 0 + + return ret +} + + +/***/ }), + +/***/ 198: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const core = __importStar(__webpack_require__(470)); +const create_pull_request_1 = __webpack_require__(940); +const util_1 = __webpack_require__(669); +const utils = __importStar(__webpack_require__(611)); +function run() { + return __awaiter(this, void 0, void 0, function* () { + try { + const inputs = { + token: core.getInput('token'), + path: core.getInput('path'), + commitMessage: core.getInput('commit-message'), + committer: core.getInput('committer'), + author: core.getInput('author'), + title: core.getInput('title'), + body: core.getInput('body'), + labels: utils.getInputAsArray('labels'), + assignees: utils.getInputAsArray('assignees'), + reviewers: utils.getInputAsArray('reviewers'), + teamReviewers: utils.getInputAsArray('team-reviewers'), + milestone: Number(core.getInput('milestone')), + draft: core.getInput('draft') === 'true', + branch: core.getInput('branch'), + requestToParent: core.getInput('request-to-parent') === 'true', + base: core.getInput('base'), + branchSuffix: core.getInput('branch-suffix') + }; + core.debug(`Inputs: ${util_1.inspect(inputs)}`); + yield create_pull_request_1.createPullRequest(inputs); + } + catch (error) { + core.setFailed(error.message); + } + }); +} +run(); + + +/***/ }), + +/***/ 209: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _v = _interopRequireDefault(__webpack_require__(212)); + +var _md = _interopRequireDefault(__webpack_require__(803)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports.default = _default; + +/***/ }), + +/***/ 211: +/***/ (function(module) { + +module.exports = require("https"); + +/***/ }), + +/***/ 212: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _default; +exports.URL = exports.DNS = void 0; + +var _bytesToUuid = _interopRequireDefault(__webpack_require__(390)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function uuidToBytes(uuid) { + // Note: We assume we're being passed a valid uuid string + const bytes = []; + uuid.replace(/[a-fA-F0-9]{2}/g, function (hex) { + bytes.push(parseInt(hex, 16)); + }); + return bytes; +} + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function _default(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = uuidToBytes(namespace); + } + + if (!Array.isArray(value)) { + throw TypeError('value must be an array of bytes'); + } + + if (!Array.isArray(namespace) || namespace.length !== 16) { + throw TypeError('namespace must be uuid string or an Array of 16 byte values'); + } // Per 4.3 + + + const bytes = hashfunc(namespace.concat(value)); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _bytesToUuid.default)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 260: +/***/ (function(module, __unusedexports, __webpack_require__) { + +// Note: since nyc uses this module to output coverage, any lines +// that are in the direct sync flow of nyc's outputCoverage are +// ignored, since we can never get coverage for them. +var assert = __webpack_require__(357) +var signals = __webpack_require__(654) +var isWin = /^win/i.test(process.platform) + +var EE = __webpack_require__(614) +/* istanbul ignore if */ +if (typeof EE !== 'function') { + EE = EE.EventEmitter +} + +var emitter +if (process.__signal_exit_emitter__) { + emitter = process.__signal_exit_emitter__ +} else { + emitter = process.__signal_exit_emitter__ = new EE() + emitter.count = 0 + emitter.emitted = {} +} + +// Because this emitter is a global, we have to check to see if a +// previous version of this library failed to enable infinite listeners. +// I know what you're about to say. But literally everything about +// signal-exit is a compromise with evil. Get used to it. +if (!emitter.infinite) { + emitter.setMaxListeners(Infinity) + emitter.infinite = true +} + +module.exports = function (cb, opts) { + assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler') + + if (loaded === false) { + load() + } + + var ev = 'exit' + if (opts && opts.alwaysLast) { + ev = 'afterexit' + } + + var remove = function () { + emitter.removeListener(ev, cb) + if (emitter.listeners('exit').length === 0 && + emitter.listeners('afterexit').length === 0) { + unload() + } + } + emitter.on(ev, cb) + + return remove +} + +module.exports.unload = unload +function unload () { + if (!loaded) { + return + } + loaded = false + + signals.forEach(function (sig) { + try { + process.removeListener(sig, sigListeners[sig]) + } catch (er) {} + }) + process.emit = originalProcessEmit + process.reallyExit = originalProcessReallyExit + emitter.count -= 1 +} + +function emit (event, code, signal) { + if (emitter.emitted[event]) { + return + } + emitter.emitted[event] = true + emitter.emit(event, code, signal) +} + +// { : , ... } +var sigListeners = {} +signals.forEach(function (sig) { + sigListeners[sig] = function listener () { + // If there are no other listeners, an exit is coming! + // Simplest way: remove us and then re-send the signal. + // We know that this will kill the process, so we can + // safely emit now. + var listeners = process.listeners(sig) + if (listeners.length === emitter.count) { + unload() + emit('exit', null, sig) + /* istanbul ignore next */ + emit('afterexit', null, sig) + /* istanbul ignore next */ + if (isWin && sig === 'SIGHUP') { + // "SIGHUP" throws an `ENOSYS` error on Windows, + // so use a supported signal instead + sig = 'SIGINT' + } + process.kill(process.pid, sig) + } + } +}) + +module.exports.signals = function () { + return signals +} + +module.exports.load = load + +var loaded = false + +function load () { + if (loaded) { + return + } + loaded = true + + // This is the number of onSignalExit's that are in play. + // It's important so that we can count the correct number of + // listeners on signals, and don't wait for the other one to + // handle it instead of us. + emitter.count += 1 + + signals = signals.filter(function (sig) { + try { + process.on(sig, sigListeners[sig]) + return true + } catch (er) { + return false + } + }) + + process.emit = processEmit + process.reallyExit = processReallyExit +} + +var originalProcessReallyExit = process.reallyExit +function processReallyExit (code) { + process.exitCode = code || 0 + emit('exit', process.exitCode, null) + /* istanbul ignore next */ + emit('afterexit', process.exitCode, null) + /* istanbul ignore next */ + originalProcessReallyExit.call(process, process.exitCode) +} + +var originalProcessEmit = process.emit +function processEmit (ev, arg) { + if (ev === 'exit') { + if (arg !== undefined) { + process.exitCode = arg + } + var ret = originalProcessEmit.apply(this, arguments) + emit('exit', process.exitCode, null) + /* istanbul ignore next */ + emit('afterexit', process.exitCode, null) + return ret + } else { + return originalProcessEmit.apply(this, arguments) + } +} + + +/***/ }), + +/***/ 280: +/***/ (function(module) { + +module.exports = register + +function register (state, name, method, options) { + if (typeof method !== 'function') { + throw new Error('method for before hook must be a function') + } + + if (!options) { + options = {} + } + + if (Array.isArray(name)) { + return name.reverse().reduce(function (callback, name) { + return register.bind(null, state, name, callback, options) + }, method)() + } + + return Promise.resolve() + .then(function () { + if (!state.registry[name]) { + return method(options) + } + + return (state.registry[name]).reduce(function (method, registered) { + return registered.hook.bind(null, method, options) + }, method)() + }) +} + + +/***/ }), + +/***/ 289: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GitCommandManager = void 0; +const exec = __importStar(__webpack_require__(986)); +const io = __importStar(__webpack_require__(1)); +const tagsRefSpec = '+refs/tags/*:refs/tags/*'; +class GitCommandManager { + constructor(workingDirectory, gitPath) { + this.workingDirectory = workingDirectory; + this.gitPath = gitPath; + } + static create(workingDirectory) { + return __awaiter(this, void 0, void 0, function* () { + const gitPath = yield io.which('git', true); + return new GitCommandManager(workingDirectory, gitPath); + }); + } + setAuthGitOptions(authGitOptions) { + this.authGitOptions = authGitOptions; + } + setIdentityGitOptions(identityGitOptions) { + this.identityGitOptions = identityGitOptions; + } + checkout(ref, startPoint) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['checkout', '--progress']; + if (startPoint) { + args.push('-B', ref, startPoint); + } + else { + args.push(ref); + } + yield this.exec(args); + }); + } + cherryPick(options, allowAllExitCodes = false) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['cherry-pick']; + if (this.identityGitOptions) { + args.unshift(...this.identityGitOptions); + } + if (options) { + args.push(...options); + } + return yield this.exec(args, allowAllExitCodes); + }); + } + commit(options) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['commit']; + if (this.identityGitOptions) { + args.unshift(...this.identityGitOptions); + } + if (options) { + args.push(...options); + } + yield this.exec(args); + }); + } + diff(options) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['-c', 'core.pager=cat', 'diff']; + if (options) { + args.push(...options); + } + const output = yield this.exec(args); + return output.stdout.trim(); + }); + } + fetch(refSpec, remoteName, options) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['-c', 'protocol.version=2']; + if (this.authGitOptions) { + args.push(...this.authGitOptions); + } + args.push('fetch'); + if (!refSpec.some(x => x === tagsRefSpec)) { + args.push('--no-tags'); + } + args.push('--progress', '--no-recurse-submodules'); + if (options) { + args.push(...options); + } + if (remoteName) { + args.push(remoteName); + } + else { + args.push('origin'); + } + for (const arg of refSpec) { + args.push(arg); + } + yield this.exec(args); + }); + } + getWorkingDirectory() { + return this.workingDirectory; + } + isDirty(untracked) { + return __awaiter(this, void 0, void 0, function* () { + const diffArgs = ['--abbrev=40', '--full-index', '--raw']; + // Check staged changes + if (yield this.diff([...diffArgs, '--staged'])) { + return true; + } + // Check working index changes + if (yield this.diff(diffArgs)) { + return true; + } + // Check untracked changes + if (untracked && (yield this.status(['--porcelain', '-unormal']))) { + return true; + } + return false; + }); + } + push(options) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['push']; + if (this.authGitOptions) { + args.unshift(...this.authGitOptions); + } + if (options) { + args.push(...options); + } + yield this.exec(args); + }); + } + revList(commitExpression, options) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['rev-list']; + if (options) { + args.push(...options); + } + args.push(...commitExpression); + const output = yield this.exec(args); + return output.stdout.trim(); + }); + } + revParse(ref, options) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['rev-parse']; + if (options) { + args.push(...options); + } + args.push(ref); + const output = yield this.exec(args); + return output.stdout.trim(); + }); + } + status(options) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['status']; + if (options) { + args.push(...options); + } + const output = yield this.exec(args); + return output.stdout.trim(); + }); + } + symbolicRef(ref, options) { + return __awaiter(this, void 0, void 0, function* () { + const args = ['symbolic-ref', ref]; + if (options) { + args.push(...options); + } + const output = yield this.exec(args); + return output.stdout.trim(); + }); + } + tryConfigUnset(configKey, globalConfig) { + return __awaiter(this, void 0, void 0, function* () { + const output = yield this.exec([ + 'config', + globalConfig ? '--global' : '--local', + '--unset-all', + configKey + ], true); + return output.exitCode === 0; + }); + } + tryGetFetchUrl() { + return __awaiter(this, void 0, void 0, function* () { + const output = yield this.exec(['config', '--local', '--get', 'remote.origin.url'], true); + if (output.exitCode !== 0) { + return ''; + } + const stdout = output.stdout.trim(); + if (stdout.includes('\n')) { + return ''; + } + return stdout; + }); + } + exec(args, allowAllExitCodes = false) { + return __awaiter(this, void 0, void 0, function* () { + const result = new GitOutput(); + const env = {}; + for (const key of Object.keys(process.env)) { + env[key] = process.env[key]; + } + const stdout = []; + const stderr = []; + const options = { + cwd: this.workingDirectory, + env, + ignoreReturnCode: allowAllExitCodes, + listeners: { + stdout: (data) => { + stdout.push(data.toString()); + }, + stderr: (data) => { + stderr.push(data.toString()); + } + } + }; + result.exitCode = yield exec.exec(`"${this.gitPath}"`, args, options); + result.stdout = stdout.join(''); + result.stderr = stderr.join(''); + return result; + }); + } +} +exports.GitCommandManager = GitCommandManager; +class GitOutput { + constructor() { + this.stdout = ''; + this.stderr = ''; + this.exitCode = 0; + } +} + + +/***/ }), + +/***/ 299: +/***/ (function(__unusedmodule, exports) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +const VERSION = "2.2.3"; + +/** + * Some “list” response that can be paginated have a different response structure + * + * They have a `total_count` key in the response (search also has `incomplete_results`, + * /installation/repositories also has `repository_selection`), as well as a key with + * the list of the items which name varies from endpoint to endpoint. + * + * Octokit normalizes these responses so that paginated results are always returned following + * the same structure. One challenge is that if the list response has only one page, no Link + * header is provided, so this header alone is not sufficient to check wether a response is + * paginated or not. + * + * We check if a "total_count" key is present in the response data, but also make sure that + * a "url" property is not, as the "Get the combined status for a specific ref" endpoint would + * otherwise match: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref + */ +function normalizePaginatedListResponse(response) { + const responseNeedsNormalization = "total_count" in response.data && !("url" in response.data); + if (!responseNeedsNormalization) return response; // keep the additional properties intact as there is currently no other way + // to retrieve the same information. + + const incompleteResults = response.data.incomplete_results; + const repositorySelection = response.data.repository_selection; + const totalCount = response.data.total_count; + delete response.data.incomplete_results; + delete response.data.repository_selection; + delete response.data.total_count; + const namespaceKey = Object.keys(response.data)[0]; + const data = response.data[namespaceKey]; + response.data = data; + + if (typeof incompleteResults !== "undefined") { + response.data.incomplete_results = incompleteResults; + } + + if (typeof repositorySelection !== "undefined") { + response.data.repository_selection = repositorySelection; + } + + response.data.total_count = totalCount; + return response; +} + +function iterator(octokit, route, parameters) { + const options = typeof route === "function" ? route.endpoint(parameters) : octokit.request.endpoint(route, parameters); + const requestMethod = typeof route === "function" ? route : octokit.request; + const method = options.method; + const headers = options.headers; + let url = options.url; + return { + [Symbol.asyncIterator]: () => ({ + next() { + if (!url) { + return Promise.resolve({ + done: true + }); + } + + return requestMethod({ + method, + url, + headers + }).then(normalizePaginatedListResponse).then(response => { + // `response.headers.link` format: + // '; rel="next", ; rel="last"' + // sets `url` to undefined if "next" URL is not present or `link` header is not set + url = ((response.headers.link || "").match(/<([^>]+)>;\s*rel="next"/) || [])[1]; + return { + value: response + }; + }); + } + + }) + }; +} + +function paginate(octokit, route, parameters, mapFn) { + if (typeof parameters === "function") { + mapFn = parameters; + parameters = undefined; + } + + return gather(octokit, [], iterator(octokit, route, parameters)[Symbol.asyncIterator](), mapFn); +} + +function gather(octokit, results, iterator, mapFn) { + return iterator.next().then(result => { + if (result.done) { + return results; + } + + let earlyExit = false; + + function done() { + earlyExit = true; + } + + results = results.concat(mapFn ? mapFn(result.value, done) : result.value.data); + + if (earlyExit) { + return results; + } + + return gather(octokit, results, iterator, mapFn); + }); +} + +/** + * @param octokit Octokit instance + * @param options Options passed to Octokit constructor + */ + +function paginateRest(octokit) { + return { + paginate: Object.assign(paginate.bind(null, octokit), { + iterator: iterator.bind(null, octokit) + }) + }; +} +paginateRest.VERSION = VERSION; + +exports.paginateRest = paginateRest; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 306: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + + +const fs = __webpack_require__(747); +const shebangCommand = __webpack_require__(907); + +function readShebang(command) { + // Read the first 150 bytes from the file + const size = 150; + let buffer; + + if (Buffer.alloc) { + // Node.js v4.5+ / v5.10+ + buffer = Buffer.alloc(size); + } else { + // Old Node.js API + buffer = new Buffer(size); + buffer.fill(0); // zero-fill + } + + let fd; + + try { + fd = fs.openSync(command, 'r'); + fs.readSync(fd, buffer, 0, size, 0); + fs.closeSync(fd); + } catch (e) { /* Empty */ } + + // Attempt to extract shebang (null is returned if not a shebang) + return shebangCommand(buffer.toString()); +} + +module.exports = readShebang; + + +/***/ }), + +/***/ 323: +/***/ (function(module) { + +"use strict"; + + +var isStream = module.exports = function (stream) { + return stream !== null && typeof stream === 'object' && typeof stream.pipe === 'function'; +}; + +isStream.writable = function (stream) { + return isStream(stream) && stream.writable !== false && typeof stream._write === 'function' && typeof stream._writableState === 'object'; +}; + +isStream.readable = function (stream) { + return isStream(stream) && stream.readable !== false && typeof stream._read === 'function' && typeof stream._readableState === 'object'; +}; + +isStream.duplex = function (stream) { + return isStream.writable(stream) && isStream.readable(stream); +}; + +isStream.transform = function (stream) { + return isStream.duplex(stream) && typeof stream._transform === 'function' && typeof stream._transformState === 'object'; +}; + + +/***/ }), + +/***/ 357: +/***/ (function(module) { + +module.exports = require("assert"); + +/***/ }), + +/***/ 384: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _v = _interopRequireDefault(__webpack_require__(212)); + +var _sha = _interopRequireDefault(__webpack_require__(498)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports.default = _default; + +/***/ }), + +/***/ 385: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var isPlainObject = _interopDefault(__webpack_require__(626)); +var universalUserAgent = __webpack_require__(796); + +function lowercaseKeys(object) { + if (!object) { + return {}; + } + + return Object.keys(object).reduce((newObj, key) => { + newObj[key.toLowerCase()] = object[key]; + return newObj; + }, {}); +} + +function mergeDeep(defaults, options) { + const result = Object.assign({}, defaults); + Object.keys(options).forEach(key => { + if (isPlainObject(options[key])) { + if (!(key in defaults)) Object.assign(result, { + [key]: options[key] + });else result[key] = mergeDeep(defaults[key], options[key]); + } else { + Object.assign(result, { + [key]: options[key] + }); + } + }); + return result; +} + +function merge(defaults, route, options) { + if (typeof route === "string") { + let [method, url] = route.split(" "); + options = Object.assign(url ? { + method, + url + } : { + url: method + }, options); + } else { + options = Object.assign({}, route); + } // lowercase header names before merging with defaults to avoid duplicates + + + options.headers = lowercaseKeys(options.headers); + const mergedOptions = mergeDeep(defaults || {}, options); // mediaType.previews arrays are merged, instead of overwritten + + if (defaults && defaults.mediaType.previews.length) { + mergedOptions.mediaType.previews = defaults.mediaType.previews.filter(preview => !mergedOptions.mediaType.previews.includes(preview)).concat(mergedOptions.mediaType.previews); + } + + mergedOptions.mediaType.previews = mergedOptions.mediaType.previews.map(preview => preview.replace(/-preview/, "")); + return mergedOptions; +} + +function addQueryParameters(url, parameters) { + const separator = /\?/.test(url) ? "&" : "?"; + const names = Object.keys(parameters); + + if (names.length === 0) { + return url; + } + + return url + separator + names.map(name => { + if (name === "q") { + return "q=" + parameters.q.split("+").map(encodeURIComponent).join("+"); + } + + return `${name}=${encodeURIComponent(parameters[name])}`; + }).join("&"); +} + +const urlVariableRegex = /\{[^}]+\}/g; + +function removeNonChars(variableName) { + return variableName.replace(/^\W+|\W+$/g, "").split(/,/); +} + +function extractUrlVariableNames(url) { + const matches = url.match(urlVariableRegex); + + if (!matches) { + return []; + } + + return matches.map(removeNonChars).reduce((a, b) => a.concat(b), []); +} + +function omit(object, keysToOmit) { + return Object.keys(object).filter(option => !keysToOmit.includes(option)).reduce((obj, key) => { + obj[key] = object[key]; + return obj; + }, {}); +} + +// Based on https://github.com/bramstein/url-template, licensed under BSD +// TODO: create separate package. +// +// Copyright (c) 2012-2014, Bram Stein +// All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* istanbul ignore file */ +function encodeReserved(str) { + return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) { + if (!/%[0-9A-Fa-f]/.test(part)) { + part = encodeURI(part).replace(/%5B/g, "[").replace(/%5D/g, "]"); + } + + return part; + }).join(""); +} + +function encodeUnreserved(str) { + return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { + return "%" + c.charCodeAt(0).toString(16).toUpperCase(); + }); +} + +function encodeValue(operator, value, key) { + value = operator === "+" || operator === "#" ? encodeReserved(value) : encodeUnreserved(value); + + if (key) { + return encodeUnreserved(key) + "=" + value; + } else { + return value; + } +} + +function isDefined(value) { + return value !== undefined && value !== null; +} + +function isKeyOperator(operator) { + return operator === ";" || operator === "&" || operator === "?"; +} + +function getValues(context, operator, key, modifier) { + var value = context[key], + result = []; + + if (isDefined(value) && value !== "") { + if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { + value = value.toString(); + + if (modifier && modifier !== "*") { + value = value.substring(0, parseInt(modifier, 10)); + } + + result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : "")); + } else { + if (modifier === "*") { + if (Array.isArray(value)) { + value.filter(isDefined).forEach(function (value) { + result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : "")); + }); + } else { + Object.keys(value).forEach(function (k) { + if (isDefined(value[k])) { + result.push(encodeValue(operator, value[k], k)); + } + }); + } + } else { + const tmp = []; + + if (Array.isArray(value)) { + value.filter(isDefined).forEach(function (value) { + tmp.push(encodeValue(operator, value)); + }); + } else { + Object.keys(value).forEach(function (k) { + if (isDefined(value[k])) { + tmp.push(encodeUnreserved(k)); + tmp.push(encodeValue(operator, value[k].toString())); + } + }); + } + + if (isKeyOperator(operator)) { + result.push(encodeUnreserved(key) + "=" + tmp.join(",")); + } else if (tmp.length !== 0) { + result.push(tmp.join(",")); + } + } + } + } else { + if (operator === ";") { + if (isDefined(value)) { + result.push(encodeUnreserved(key)); + } + } else if (value === "" && (operator === "&" || operator === "?")) { + result.push(encodeUnreserved(key) + "="); + } else if (value === "") { + result.push(""); + } + } + + return result; +} + +function parseUrl(template) { + return { + expand: expand.bind(null, template) + }; +} + +function expand(template, context) { + var operators = ["+", "#", ".", "/", ";", "?", "&"]; + return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { + if (expression) { + let operator = ""; + const values = []; + + if (operators.indexOf(expression.charAt(0)) !== -1) { + operator = expression.charAt(0); + expression = expression.substr(1); + } + + expression.split(/,/g).forEach(function (variable) { + var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); + values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3])); + }); + + if (operator && operator !== "+") { + var separator = ","; + + if (operator === "?") { + separator = "&"; + } else if (operator !== "#") { + separator = operator; + } + + return (values.length !== 0 ? operator : "") + values.join(separator); + } else { + return values.join(","); + } + } else { + return encodeReserved(literal); + } + }); +} + +function parse(options) { + // https://fetch.spec.whatwg.org/#methods + let method = options.method.toUpperCase(); // replace :varname with {varname} to make it RFC 6570 compatible + + let url = (options.url || "/").replace(/:([a-z]\w+)/g, "{+$1}"); + let headers = Object.assign({}, options.headers); + let body; + let parameters = omit(options, ["method", "baseUrl", "url", "headers", "request", "mediaType"]); // extract variable names from URL to calculate remaining variables later + + const urlVariableNames = extractUrlVariableNames(url); + url = parseUrl(url).expand(parameters); + + if (!/^http/.test(url)) { + url = options.baseUrl + url; + } + + const omittedParameters = Object.keys(options).filter(option => urlVariableNames.includes(option)).concat("baseUrl"); + const remainingParameters = omit(parameters, omittedParameters); + const isBinaryRequset = /application\/octet-stream/i.test(headers.accept); + + if (!isBinaryRequset) { + if (options.mediaType.format) { + // e.g. application/vnd.github.v3+json => application/vnd.github.v3.raw + headers.accept = headers.accept.split(/,/).map(preview => preview.replace(/application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/, `application/vnd$1$2.${options.mediaType.format}`)).join(","); + } + + if (options.mediaType.previews.length) { + const previewsFromAcceptHeader = headers.accept.match(/[\w-]+(?=-preview)/g) || []; + headers.accept = previewsFromAcceptHeader.concat(options.mediaType.previews).map(preview => { + const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json"; + return `application/vnd.github.${preview}-preview${format}`; + }).join(","); + } + } // for GET/HEAD requests, set URL query parameters from remaining parameters + // for PATCH/POST/PUT/DELETE requests, set request body from remaining parameters + + + if (["GET", "HEAD"].includes(method)) { + url = addQueryParameters(url, remainingParameters); + } else { + if ("data" in remainingParameters) { + body = remainingParameters.data; + } else { + if (Object.keys(remainingParameters).length) { + body = remainingParameters; + } else { + headers["content-length"] = 0; + } + } + } // default content-type for JSON if body is set + + + if (!headers["content-type"] && typeof body !== "undefined") { + headers["content-type"] = "application/json; charset=utf-8"; + } // GitHub expects 'content-length: 0' header for PUT/PATCH requests without body. + // fetch does not allow to set `content-length` header, but we can set body to an empty string + + + if (["PATCH", "PUT"].includes(method) && typeof body === "undefined") { + body = ""; + } // Only return body/request keys if present + + + return Object.assign({ + method, + url, + headers + }, typeof body !== "undefined" ? { + body + } : null, options.request ? { + request: options.request + } : null); +} + +function endpointWithDefaults(defaults, route, options) { + return parse(merge(defaults, route, options)); +} + +function withDefaults(oldDefaults, newDefaults) { + const DEFAULTS = merge(oldDefaults, newDefaults); + const endpoint = endpointWithDefaults.bind(null, DEFAULTS); + return Object.assign(endpoint, { + DEFAULTS, + defaults: withDefaults.bind(null, DEFAULTS), + merge: merge.bind(null, DEFAULTS), + parse + }); +} + +const VERSION = "6.0.3"; + +const userAgent = `octokit-endpoint.js/${VERSION} ${universalUserAgent.getUserAgent()}`; // DEFAULTS has all properties set that EndpointOptions has, except url. +// So we use RequestParameters and add method as additional required property. + +const DEFAULTS = { + method: "GET", + baseUrl: "https://api.github.com", + headers: { + accept: "application/vnd.github.v3+json", + "user-agent": userAgent + }, + mediaType: { + format: "", + previews: [] + } +}; + +const endpoint = withDefaults(null, DEFAULTS); + +exports.endpoint = endpoint; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 390: +/***/ (function(__unusedmodule, exports) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).substr(1)); +} + +function bytesToUuid(buf, offset_) { + const offset = offset_ || 0; // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + + return (byteToHex[buf[offset + 0]] + byteToHex[buf[offset + 1]] + byteToHex[buf[offset + 2]] + byteToHex[buf[offset + 3]] + '-' + byteToHex[buf[offset + 4]] + byteToHex[buf[offset + 5]] + '-' + byteToHex[buf[offset + 6]] + byteToHex[buf[offset + 7]] + '-' + byteToHex[buf[offset + 8]] + byteToHex[buf[offset + 9]] + '-' + byteToHex[buf[offset + 10]] + byteToHex[buf[offset + 11]] + byteToHex[buf[offset + 12]] + byteToHex[buf[offset + 13]] + byteToHex[buf[offset + 14]] + byteToHex[buf[offset + 15]]).toLowerCase(); +} + +var _default = bytesToUuid; +exports.default = _default; + +/***/ }), + +/***/ 413: +/***/ (function(module) { + +module.exports = require("stream"); + +/***/ }), + +/***/ 417: +/***/ (function(module) { + +module.exports = require("crypto"); + +/***/ }), + +/***/ 427: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +// Older verions of Node.js might not have `util.getSystemErrorName()`. +// In that case, fall back to a deprecated internal. +const util = __webpack_require__(669); + +let uv; + +if (typeof util.getSystemErrorName === 'function') { + module.exports = util.getSystemErrorName; +} else { + try { + uv = process.binding('uv'); + + if (typeof uv.errname !== 'function') { + throw new TypeError('uv.errname is not a function'); + } + } catch (err) { + console.error('execa/lib/errname: unable to establish process.binding(\'uv\')', err); + uv = null; + } + + module.exports = code => errname(uv, code); +} + +// Used for testing the fallback behavior +module.exports.__test__ = errname; + +function errname(uv, code) { + if (uv) { + return uv.errname(code); + } + + if (!(code < 0)) { + throw new Error('err >= 0'); + } + + return `Unknown system error ${code}`; +} + + + +/***/ }), + +/***/ 431: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const os = __importStar(__webpack_require__(87)); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +exports.toCommandValue = toCommandValue; +function escapeData(s) { + return toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map + +/***/ }), + +/***/ 448: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +var universalUserAgent = __webpack_require__(796); +var beforeAfterHook = __webpack_require__(523); +var request = __webpack_require__(753); +var graphql = __webpack_require__(898); +var authToken = __webpack_require__(813); + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + if (enumerableOnly) symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + keys.push.apply(keys, symbols); + } + + return keys; +} + +function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + + if (i % 2) { + ownKeys(Object(source), true).forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + + return target; +} + +const VERSION = "3.1.0"; + +class Octokit { + constructor(options = {}) { + const hook = new beforeAfterHook.Collection(); + const requestDefaults = { + baseUrl: request.request.endpoint.DEFAULTS.baseUrl, + headers: {}, + request: Object.assign({}, options.request, { + hook: hook.bind(null, "request") + }), + mediaType: { + previews: [], + format: "" + } + }; // prepend default user agent with `options.userAgent` if set + + requestDefaults.headers["user-agent"] = [options.userAgent, `octokit-core.js/${VERSION} ${universalUserAgent.getUserAgent()}`].filter(Boolean).join(" "); + + if (options.baseUrl) { + requestDefaults.baseUrl = options.baseUrl; + } + + if (options.previews) { + requestDefaults.mediaType.previews = options.previews; + } + + if (options.timeZone) { + requestDefaults.headers["time-zone"] = options.timeZone; + } + + this.request = request.request.defaults(requestDefaults); + this.graphql = graphql.withCustomRequest(this.request).defaults(_objectSpread2(_objectSpread2({}, requestDefaults), {}, { + baseUrl: requestDefaults.baseUrl.replace(/\/api\/v3$/, "/api") + })); + this.log = Object.assign({ + debug: () => {}, + info: () => {}, + warn: console.warn.bind(console), + error: console.error.bind(console) + }, options.log); + this.hook = hook; // (1) If neither `options.authStrategy` nor `options.auth` are set, the `octokit` instance + // is unauthenticated. The `this.auth()` method is a no-op and no request hook is registred. + // (2) If only `options.auth` is set, use the default token authentication strategy. + // (3) If `options.authStrategy` is set then use it and pass in `options.auth`. Always pass own request as many strategies accept a custom request instance. + // TODO: type `options.auth` based on `options.authStrategy`. + + if (!options.authStrategy) { + if (!options.auth) { + // (1) + this.auth = async () => ({ + type: "unauthenticated" + }); + } else { + // (2) + const auth = authToken.createTokenAuth(options.auth); // @ts-ignore ¯\_(ツ)_/¯ + + hook.wrap("request", auth.hook); + this.auth = auth; + } + } else { + const auth = options.authStrategy(Object.assign({ + request: this.request + }, options.auth)); // @ts-ignore ¯\_(ツ)_/¯ + + hook.wrap("request", auth.hook); + this.auth = auth; + } // apply plugins + // https://stackoverflow.com/a/16345172 + + + const classConstructor = this.constructor; + classConstructor.plugins.forEach(plugin => { + Object.assign(this, plugin(this, options)); + }); + } + + static defaults(defaults) { + const OctokitWithDefaults = class extends this { + constructor(...args) { + const options = args[0] || {}; + + if (typeof defaults === "function") { + super(defaults(options)); + return; + } + + super(Object.assign({}, defaults, options, options.userAgent && defaults.userAgent ? { + userAgent: `${options.userAgent} ${defaults.userAgent}` + } : null)); + } + + }; + return OctokitWithDefaults; + } + /** + * Attach a plugin (or many) to your Octokit instance. + * + * @example + * const API = Octokit.plugin(plugin1, plugin2, plugin3, ...) + */ + + + static plugin(...newPlugins) { + var _a; + + const currentPlugins = this.plugins; + const NewOctokit = (_a = class extends this {}, _a.plugins = currentPlugins.concat(newPlugins.filter(plugin => !currentPlugins.includes(plugin))), _a); + return NewOctokit; + } + +} +Octokit.VERSION = VERSION; +Octokit.plugins = []; + +exports.Octokit = Octokit; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 453: +/***/ (function(module, __unusedexports, __webpack_require__) { + +var once = __webpack_require__(969) +var eos = __webpack_require__(9) +var fs = __webpack_require__(747) // we only need fs to get the ReadStream and WriteStream prototypes + +var noop = function () {} +var ancient = /^v?\.0/.test(process.version) + +var isFn = function (fn) { + return typeof fn === 'function' +} + +var isFS = function (stream) { + if (!ancient) return false // newer node version do not need to care about fs is a special way + if (!fs) return false // browser + return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close) +} + +var isRequest = function (stream) { + return stream.setHeader && isFn(stream.abort) +} + +var destroyer = function (stream, reading, writing, callback) { + callback = once(callback) + + var closed = false + stream.on('close', function () { + closed = true + }) + + eos(stream, {readable: reading, writable: writing}, function (err) { + if (err) return callback(err) + closed = true + callback() + }) + + var destroyed = false + return function (err) { + if (closed) return + if (destroyed) return + destroyed = true + + if (isFS(stream)) return stream.close(noop) // use close for fs streams to avoid fd leaks + if (isRequest(stream)) return stream.abort() // request.destroy just do .end - .abort is what we want + + if (isFn(stream.destroy)) return stream.destroy() + + callback(err || new Error('stream was destroyed')) + } +} + +var call = function (fn) { + fn() +} + +var pipe = function (from, to) { + return from.pipe(to) +} + +var pump = function () { + var streams = Array.prototype.slice.call(arguments) + var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop + + if (Array.isArray(streams[0])) streams = streams[0] + if (streams.length < 2) throw new Error('pump requires two streams per minimum') + + var error + var destroys = streams.map(function (stream, i) { + var reading = i < streams.length - 1 + var writing = i > 0 + return destroyer(stream, reading, writing, function (err) { + if (!error) error = err + if (err) destroys.forEach(call) + if (reading) return + destroys.forEach(call) + callback(error) + }) + }) + + return streams.reduce(pipe) +} + +module.exports = pump + + +/***/ }), + +/***/ 454: +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var Stream = _interopDefault(__webpack_require__(413)); +var http = _interopDefault(__webpack_require__(605)); +var Url = _interopDefault(__webpack_require__(835)); +var https = _interopDefault(__webpack_require__(211)); +var zlib = _interopDefault(__webpack_require__(761)); + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = __webpack_require__(18).convert; +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parse_url(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parse_url(`${input}`); + } + input = {}; + } else { + parsedURL = parse_url(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + if (!headers.has('Connection') && !agent) { + headers.set('Connection', 'close'); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; +const resolve_url = Url.resolve; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + request.body.destroy(error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + finalize(); + }); + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + const locationURL = location === null ? null : resolve_url(request.url, location); + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout + }; + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +module.exports = exports = fetch; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = exports; +exports.Headers = Headers; +exports.Request = Request; +exports.Response = Response; +exports.FetchError = FetchError; + + +/***/ }), + +/***/ 463: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var deprecation = __webpack_require__(692); +var once = _interopDefault(__webpack_require__(969)); + +const logOnce = once(deprecation => console.warn(deprecation)); +/** + * Error with extra properties to help with debugging + */ + +class RequestError extends Error { + constructor(message, statusCode, options) { + super(message); // Maintains proper stack trace (only available on V8) + + /* istanbul ignore next */ + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + + this.name = "HttpError"; + this.status = statusCode; + Object.defineProperty(this, "code", { + get() { + logOnce(new deprecation.Deprecation("[@octokit/request-error] `error.code` is deprecated, use `error.status`.")); + return statusCode; + } + + }); + this.headers = options.headers || {}; // redact request credentials without mutating original request options + + const requestCopy = Object.assign({}, options.request); + + if (options.request.headers.authorization) { + requestCopy.headers = Object.assign({}, options.request.headers, { + authorization: options.request.headers.authorization.replace(/ .*$/, " [REDACTED]") + }); + } + + requestCopy.url = requestCopy.url // client_id & client_secret can be passed as URL query parameters to increase rate limit + // see https://developer.github.com/v3/#increasing-the-unauthenticated-rate-limit-for-oauth-applications + .replace(/\bclient_secret=\w+/g, "client_secret=[REDACTED]") // OAuth tokens can be passed as URL query parameters, although it is not recommended + // see https://developer.github.com/v3/#oauth2-token-sent-in-a-header + .replace(/\baccess_token=\w+/g, "access_token=[REDACTED]"); + this.request = requestCopy; + } + +} + +exports.RequestError = RequestError; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 468: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GitConfigHelper = exports.ConfigOption = void 0; +const core = __importStar(__webpack_require__(470)); +class ConfigOption { + constructor() { + this.name = ''; + this.value = ''; + } +} +exports.ConfigOption = ConfigOption; +class GitConfigHelper { + constructor(git) { + this.git = git; + } + addConfigOption(name, value) { + return __awaiter(this, void 0, void 0, function* () { + const result = yield this.git.exec(['config', '--local', '--add', name, value], true); + return result.exitCode === 0; + }); + } + unsetConfigOption(name, valueRegex = '.') { + return __awaiter(this, void 0, void 0, function* () { + const result = yield this.git.exec(['config', '--local', '--unset', name, valueRegex], true); + return result.exitCode === 0; + }); + } + configOptionExists(name, valueRegex = '.') { + return __awaiter(this, void 0, void 0, function* () { + const result = yield this.git.exec(['config', '--local', '--name-only', '--get-regexp', name, valueRegex], true); + return result.exitCode === 0; + }); + } + getConfigOption(name, valueRegex = '.') { + return __awaiter(this, void 0, void 0, function* () { + const option = new ConfigOption(); + const result = yield this.git.exec(['config', '--local', '--get-regexp', name, valueRegex], true); + option.name = name; + option.value = result.stdout.trim().split(`${name} `)[1]; + return option; + }); + } + getAndUnsetConfigOption(name, valueRegex = '.') { + return __awaiter(this, void 0, void 0, function* () { + if (yield this.configOptionExists(name, valueRegex)) { + const option = yield this.getConfigOption(name, valueRegex); + if (yield this.unsetConfigOption(name, valueRegex)) { + core.debug(`Unset config option '${name}'`); + return option; + } + } + return new ConfigOption(); + }); + } +} +exports.GitConfigHelper = GitConfigHelper; + + +/***/ }), + +/***/ 470: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result["default"] = mod; + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const command_1 = __webpack_require__(431); +const os = __importStar(__webpack_require__(87)); +const path = __importStar(__webpack_require__(622)); +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = command_1.toCommandValue(val); + process.env[name] = convertedVal; + command_1.issueCommand('set-env', { name }, convertedVal); +} +exports.exportVariable = exportVariable; +/** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ +function setSecret(secret) { + command_1.issueCommand('add-mask', {}, secret); +} +exports.setSecret = setSecret; +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + command_1.issueCommand('add-path', {}, inputPath); + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; +} +exports.addPath = addPath; +/** + * Gets the value of an input. The value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + return val.trim(); +} +exports.getInput = getInput; +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + command_1.issueCommand('set-output', { name }, value); +} +exports.setOutput = setOutput; +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + command_1.issue('echo', enabled ? 'on' : 'off'); +} +exports.setCommandEcho = setCommandEcho; +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +exports.setFailed = setFailed; +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +exports.isDebug = isDebug; +/** + * Writes debug message to user log + * @param message debug message + */ +function debug(message) { + command_1.issueCommand('debug', {}, message); +} +exports.debug = debug; +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + */ +function error(message) { + command_1.issue('error', message instanceof Error ? message.toString() : message); +} +exports.error = error; +/** + * Adds an warning issue + * @param message warning issue message. Errors will be converted to string via toString() + */ +function warning(message) { + command_1.issue('warning', message instanceof Error ? message.toString() : message); +} +exports.warning = warning; +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + os.EOL); +} +exports.info = info; +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + command_1.issue('group', name); +} +exports.startGroup = startGroup; +/** + * End an output group. + */ +function endGroup() { + command_1.issue('endgroup'); +} +exports.endGroup = endGroup; +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +exports.group = group; +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + command_1.issueCommand('save-state', { name }, value); +} +exports.saveState = saveState; +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +exports.getState = getState; +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 473: +/***/ (function(module) { + +"use strict"; + +module.exports = /^#!.*/; + + +/***/ }), + +/***/ 498: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _crypto = _interopRequireDefault(__webpack_require__(417)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports.default = _default; + +/***/ }), + +/***/ 510: +/***/ (function(module) { + +module.exports = addHook + +function addHook (state, kind, name, hook) { + var orig = hook + if (!state.registry[name]) { + state.registry[name] = [] + } + + if (kind === 'before') { + hook = function (method, options) { + return Promise.resolve() + .then(orig.bind(null, options)) + .then(method.bind(null, options)) + } + } + + if (kind === 'after') { + hook = function (method, options) { + var result + return Promise.resolve() + .then(method.bind(null, options)) + .then(function (result_) { + result = result_ + return orig(result, options) + }) + .then(function () { + return result + }) + } + } + + if (kind === 'error') { + hook = function (method, options) { + return Promise.resolve() + .then(method.bind(null, options)) + .catch(function (error) { + return orig(error, options) + }) + } + } + + state.registry[name].push({ + hook: hook, + orig: orig + }) +} + + +/***/ }), + +/***/ 523: +/***/ (function(module, __unusedexports, __webpack_require__) { + +var register = __webpack_require__(280) +var addHook = __webpack_require__(510) +var removeHook = __webpack_require__(866) + +// bind with array of arguments: https://stackoverflow.com/a/21792913 +var bind = Function.bind +var bindable = bind.bind(bind) + +function bindApi (hook, state, name) { + var removeHookRef = bindable(removeHook, null).apply(null, name ? [state, name] : [state]) + hook.api = { remove: removeHookRef } + hook.remove = removeHookRef + + ;['before', 'error', 'after', 'wrap'].forEach(function (kind) { + var args = name ? [state, kind, name] : [state, kind] + hook[kind] = hook.api[kind] = bindable(addHook, null).apply(null, args) + }) +} + +function HookSingular () { + var singularHookName = 'h' + var singularHookState = { + registry: {} + } + var singularHook = register.bind(null, singularHookState, singularHookName) + bindApi(singularHook, singularHookState, singularHookName) + return singularHook +} + +function HookCollection () { + var state = { + registry: {} + } + + var hook = register.bind(null, state) + bindApi(hook, state) + + return hook +} + +var collectionHookDeprecationMessageDisplayed = false +function Hook () { + if (!collectionHookDeprecationMessageDisplayed) { + console.warn('[before-after-hook]: "Hook()" repurposing warning, use "Hook.Collection()". Read more: https://git.io/upgrade-before-after-hook-to-1.4') + collectionHookDeprecationMessageDisplayed = true + } + return HookCollection() +} + +Hook.Singular = HookSingular.bind() +Hook.Collection = HookCollection.bind() + +module.exports = Hook +// expose constructors as a named property for TypeScript +module.exports.Hook = Hook +module.exports.Singular = Hook.Singular +module.exports.Collection = Hook.Collection + + +/***/ }), + +/***/ 542: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + + +const path = __webpack_require__(622); +const which = __webpack_require__(55); +const pathKey = __webpack_require__(565)(); + +function resolveCommandAttempt(parsed, withoutPathExt) { + const cwd = process.cwd(); + const hasCustomCwd = parsed.options.cwd != null; + + // If a custom `cwd` was specified, we need to change the process cwd + // because `which` will do stat calls but does not support a custom cwd + if (hasCustomCwd) { + try { + process.chdir(parsed.options.cwd); + } catch (err) { + /* Empty */ + } + } + + let resolved; + + try { + resolved = which.sync(parsed.command, { + path: (parsed.options.env || process.env)[pathKey], + pathExt: withoutPathExt ? path.delimiter : undefined, + }); + } catch (e) { + /* Empty */ + } finally { + process.chdir(cwd); + } + + // If we successfully resolved, ensure that an absolute path is returned + // Note that when a custom `cwd` was used, we need to resolve to an absolute path based on it + if (resolved) { + resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : '', resolved); + } + + return resolved; +} + +function resolveCommand(parsed) { + return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true); +} + +module.exports = resolveCommand; + + +/***/ }), + +/***/ 548: +/***/ (function(module) { + +"use strict"; + + +/*! + * isobject + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +function isObject(val) { + return val != null && typeof val === 'object' && Array.isArray(val) === false; +} + +/*! + * is-plain-object + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +function isObjectObject(o) { + return isObject(o) === true + && Object.prototype.toString.call(o) === '[object Object]'; +} + +function isPlainObject(o) { + var ctor,prot; + + if (isObjectObject(o) === false) return false; + + // If has modified constructor + ctor = o.constructor; + if (typeof ctor !== 'function') return false; + + // If has modified prototype + prot = ctor.prototype; + if (isObjectObject(prot) === false) return false; + + // If constructor does not have an Object-specific method + if (prot.hasOwnProperty('isPrototypeOf') === false) { + return false; + } + + // Most likely a plain Object + return true; +} + +module.exports = isPlainObject; + + +/***/ }), + +/***/ 565: +/***/ (function(module) { + +"use strict"; + +module.exports = opts => { + opts = opts || {}; + + const env = opts.env || process.env; + const platform = opts.platform || process.platform; + + if (platform !== 'win32') { + return 'PATH'; + } + + return Object.keys(env).find(x => x.toUpperCase() === 'PATH') || 'Path'; +}; + + +/***/ }), + +/***/ 605: +/***/ (function(module) { + +module.exports = require("http"); + +/***/ }), + +/***/ 607: +/***/ (function(module, exports) { + +exports = module.exports = SemVer + +var debug +/* istanbul ignore next */ +if (typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG)) { + debug = function () { + var args = Array.prototype.slice.call(arguments, 0) + args.unshift('SEMVER') + console.log.apply(console, args) + } +} else { + debug = function () {} +} + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0' + +var MAX_LENGTH = 256 +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 + +// Max safe segment length for coercion. +var MAX_SAFE_COMPONENT_LENGTH = 16 + +// The actual regexps go on exports.re +var re = exports.re = [] +var src = exports.src = [] +var R = 0 + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +var NUMERICIDENTIFIER = R++ +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' +var NUMERICIDENTIFIERLOOSE = R++ +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +var NONNUMERICIDENTIFIER = R++ +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' + +// ## Main Version +// Three dot-separated numeric identifiers. + +var MAINVERSION = R++ +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')' + +var MAINVERSIONLOOSE = R++ +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')' + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +var PRERELEASEIDENTIFIER = R++ +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')' + +var PRERELEASEIDENTIFIERLOOSE = R++ +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')' + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +var PRERELEASE = R++ +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' + +var PRERELEASELOOSE = R++ +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +var BUILDIDENTIFIER = R++ +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +var BUILD = R++ +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +var FULL = R++ +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?' + +src[FULL] = '^' + FULLPLAIN + '$' + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?' + +var LOOSE = R++ +src[LOOSE] = '^' + LOOSEPLAIN + '$' + +var GTLT = R++ +src[GTLT] = '((?:<|>)?=?)' + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++ +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' +var XRANGEIDENTIFIER = R++ +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' + +var XRANGEPLAIN = R++ +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:' + src[PRERELEASE] + ')?' + + src[BUILD] + '?' + + ')?)?' + +var XRANGEPLAINLOOSE = R++ +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:' + src[PRERELEASELOOSE] + ')?' + + src[BUILD] + '?' + + ')?)?' + +var XRANGE = R++ +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' +var XRANGELOOSE = R++ +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +var COERCE = R++ +src[COERCE] = '(?:^|[^\\d])' + + '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:$|[^\\d])' + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++ +src[LONETILDE] = '(?:~>?)' + +var TILDETRIM = R++ +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') +var tildeTrimReplace = '$1~' + +var TILDE = R++ +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' +var TILDELOOSE = R++ +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++ +src[LONECARET] = '(?:\\^)' + +var CARETTRIM = R++ +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') +var caretTrimReplace = '$1^' + +var CARET = R++ +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' +var CARETLOOSE = R++ +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++ +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' +var COMPARATOR = R++ +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++ +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') +var comparatorTrimReplace = '$1$2$3' + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++ +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$' + +var HYPHENRANGELOOSE = R++ +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$' + +// Star ranges basically just allow anything at all. +var STAR = R++ +src[STAR] = '(<|>)?=?\\s*\\*' + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]) + if (!re[i]) { + re[i] = new RegExp(src[i]) + } +} + +exports.parse = parse +function parse (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + if (version.length > MAX_LENGTH) { + return null + } + + var r = options.loose ? re[LOOSE] : re[FULL] + if (!r.test(version)) { + return null + } + + try { + return new SemVer(version, options) + } catch (er) { + return null + } +} + +exports.valid = valid +function valid (version, options) { + var v = parse(version, options) + return v ? v.version : null +} + +exports.clean = clean +function clean (version, options) { + var s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null +} + +exports.SemVer = SemVer + +function SemVer (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + if (version instanceof SemVer) { + if (version.loose === options.loose) { + return version + } else { + version = version.version + } + } else if (typeof version !== 'string') { + throw new TypeError('Invalid Version: ' + version) + } + + if (version.length > MAX_LENGTH) { + throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + } + + if (!(this instanceof SemVer)) { + return new SemVer(version, options) + } + + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose + + var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) + + if (!m) { + throw new TypeError('Invalid Version: ' + version) + } + + this.raw = version + + // these are actually numbers + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') + } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') + } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') + } + + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map(function (id) { + if (/^[0-9]+$/.test(id)) { + var num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }) + } + + this.build = m[5] ? m[5].split('.') : [] + this.format() +} + +SemVer.prototype.format = function () { + this.version = this.major + '.' + this.minor + '.' + this.patch + if (this.prerelease.length) { + this.version += '-' + this.prerelease.join('.') + } + return this.version +} + +SemVer.prototype.toString = function () { + return this.version +} + +SemVer.prototype.compare = function (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return this.compareMain(other) || this.comparePre(other) +} + +SemVer.prototype.compareMain = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch) +} + +SemVer.prototype.comparePre = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } + + var i = 0 + do { + var a = this.prerelease[i] + var b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) +} + +// preminor will bump the version up to the next minor release, and immediately +// down to pre-release. premajor and prepatch work the same way. +SemVer.prototype.inc = function (release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break + case 'preminor': + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if (this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break + // This probably shouldn't be used publicly. + // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + var i = this.prerelease.length + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++ + i = -2 + } + } + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } + } + break + + default: + throw new Error('invalid increment argument: ' + release) + } + this.format() + this.raw = this.version + return this +} + +exports.inc = inc +function inc (version, release, loose, identifier) { + if (typeof (loose) === 'string') { + identifier = loose + loose = undefined + } + + try { + return new SemVer(version, loose).inc(release, identifier).version + } catch (er) { + return null + } +} + +exports.diff = diff +function diff (version1, version2) { + if (eq(version1, version2)) { + return null + } else { + var v1 = parse(version1) + var v2 = parse(version2) + var prefix = '' + if (v1.prerelease.length || v2.prerelease.length) { + prefix = 'pre' + var defaultResult = 'prerelease' + } + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return prefix + key + } + } + } + return defaultResult // may be undefined + } +} + +exports.compareIdentifiers = compareIdentifiers + +var numeric = /^[0-9]+$/ +function compareIdentifiers (a, b) { + var anum = numeric.test(a) + var bnum = numeric.test(b) + + if (anum && bnum) { + a = +a + b = +b + } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 +} + +exports.rcompareIdentifiers = rcompareIdentifiers +function rcompareIdentifiers (a, b) { + return compareIdentifiers(b, a) +} + +exports.major = major +function major (a, loose) { + return new SemVer(a, loose).major +} + +exports.minor = minor +function minor (a, loose) { + return new SemVer(a, loose).minor +} + +exports.patch = patch +function patch (a, loose) { + return new SemVer(a, loose).patch +} + +exports.compare = compare +function compare (a, b, loose) { + return new SemVer(a, loose).compare(new SemVer(b, loose)) +} + +exports.compareLoose = compareLoose +function compareLoose (a, b) { + return compare(a, b, true) +} + +exports.rcompare = rcompare +function rcompare (a, b, loose) { + return compare(b, a, loose) +} + +exports.sort = sort +function sort (list, loose) { + return list.sort(function (a, b) { + return exports.compare(a, b, loose) + }) +} + +exports.rsort = rsort +function rsort (list, loose) { + return list.sort(function (a, b) { + return exports.rcompare(a, b, loose) + }) +} + +exports.gt = gt +function gt (a, b, loose) { + return compare(a, b, loose) > 0 +} + +exports.lt = lt +function lt (a, b, loose) { + return compare(a, b, loose) < 0 +} + +exports.eq = eq +function eq (a, b, loose) { + return compare(a, b, loose) === 0 +} + +exports.neq = neq +function neq (a, b, loose) { + return compare(a, b, loose) !== 0 +} + +exports.gte = gte +function gte (a, b, loose) { + return compare(a, b, loose) >= 0 +} + +exports.lte = lte +function lte (a, b, loose) { + return compare(a, b, loose) <= 0 +} + +exports.cmp = cmp +function cmp (a, op, b, loose) { + switch (op) { + case '===': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a === b + + case '!==': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a !== b + + case '': + case '=': + case '==': + return eq(a, b, loose) + + case '!=': + return neq(a, b, loose) + + case '>': + return gt(a, b, loose) + + case '>=': + return gte(a, b, loose) + + case '<': + return lt(a, b, loose) + + case '<=': + return lte(a, b, loose) + + default: + throw new TypeError('Invalid operator: ' + op) + } +} + +exports.Comparator = Comparator +function Comparator (comp, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value + } + } + + if (!(this instanceof Comparator)) { + return new Comparator(comp, options) + } + + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) + + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version + } + + debug('comp', this) +} + +var ANY = {} +Comparator.prototype.parse = function (comp) { + var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var m = comp.match(r) + + if (!m) { + throw new TypeError('Invalid comparator: ' + comp) + } + + this.operator = m[1] + if (this.operator === '=') { + this.operator = '' + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } +} + +Comparator.prototype.toString = function () { + return this.value +} + +Comparator.prototype.test = function (version) { + debug('Comparator.test', version, this.options.loose) + + if (this.semver === ANY) { + return true + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + return cmp(version, this.operator, this.semver, this.options) +} + +Comparator.prototype.intersects = function (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } + + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + var rangeTmp + + if (this.operator === '') { + rangeTmp = new Range(comp.value, options) + return satisfies(this.value, rangeTmp, options) + } else if (comp.operator === '') { + rangeTmp = new Range(this.value, options) + return satisfies(comp.semver, rangeTmp, options) + } + + var sameDirectionIncreasing = + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '>=' || comp.operator === '>') + var sameDirectionDecreasing = + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '<=' || comp.operator === '<') + var sameSemVer = this.semver.version === comp.semver.version + var differentDirectionsInclusive = + (this.operator === '>=' || this.operator === '<=') && + (comp.operator === '>=' || comp.operator === '<=') + var oppositeDirectionsLessThan = + cmp(this.semver, '<', comp.semver, options) && + ((this.operator === '>=' || this.operator === '>') && + (comp.operator === '<=' || comp.operator === '<')) + var oppositeDirectionsGreaterThan = + cmp(this.semver, '>', comp.semver, options) && + ((this.operator === '<=' || this.operator === '<') && + (comp.operator === '>=' || comp.operator === '>')) + + return sameDirectionIncreasing || sameDirectionDecreasing || + (sameSemVer && differentDirectionsInclusive) || + oppositeDirectionsLessThan || oppositeDirectionsGreaterThan +} + +exports.Range = Range +function Range (range, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (range instanceof Range) { + if (range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease) { + return range + } else { + return new Range(range.raw, options) + } + } + + if (range instanceof Comparator) { + return new Range(range.value, options) + } + + if (!(this instanceof Range)) { + return new Range(range, options) + } + + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease + + // First, split based on boolean or || + this.raw = range + this.set = range.split(/\s*\|\|\s*/).map(function (range) { + return this.parseRange(range.trim()) + }, this).filter(function (c) { + // throw out any that are not relevant for whatever reason + return c.length + }) + + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range) + } + + this.format() +} + +Range.prototype.format = function () { + this.range = this.set.map(function (comps) { + return comps.join(' ').trim() + }).join('||').trim() + return this.range +} + +Range.prototype.toString = function () { + return this.range +} + +Range.prototype.parseRange = function (range) { + var loose = this.options.loose + range = range.trim() + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] + range = range.replace(hr, hyphenReplace) + debug('hyphen replace', range) + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[COMPARATORTRIM]) + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace) + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace) + + // normalize spaces + range = range.split(/\s+/).join(' ') + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var set = range.split(' ').map(function (comp) { + return parseComparator(comp, this.options) + }, this).join(' ').split(/\s+/) + if (this.options.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function (comp) { + return !!comp.match(compRe) + }) + } + set = set.map(function (comp) { + return new Comparator(comp, this.options) + }, this) + + return set +} + +Range.prototype.intersects = function (range, options) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required') + } + + return this.set.some(function (thisComparators) { + return thisComparators.every(function (thisComparator) { + return range.set.some(function (rangeComparators) { + return rangeComparators.every(function (rangeComparator) { + return thisComparator.intersects(rangeComparator, options) + }) + }) + }) + }) +} + +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators +function toComparators (range, options) { + return new Range(range, options).set.map(function (comp) { + return comp.map(function (c) { + return c.value + }).join(' ').trim().split(' ') + }) +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator (comp, options) { + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp +} + +function isX (id) { + return !id || id.toLowerCase() === 'x' || id === '*' +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceTilde(comp, options) + }).join(' ') +} + +function replaceTilde (comp, options) { + var r = options.loose ? re[TILDELOOSE] : re[TILDE] + return comp.replace(r, function (_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + // ~1.2 == >=1.2.0 <1.3.0 + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else if (pr) { + debug('replaceTilde pr', pr) + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } else { + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0' + } + + debug('tilde return', ret) + return ret + }) +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceCaret(comp, options) + }).join(' ') +} + +function replaceCaret (comp, options) { + debug('caret', comp, options) + var r = options.loose ? re[CARETLOOSE] : re[CARET] + return comp.replace(r, function (_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + if (M === '0') { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else { + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' + } + } else if (pr) { + debug('replaceCaret pr', pr) + if (M === '0') { + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + (+M + 1) + '.0.0' + } + } else { + debug('no pr') + if (M === '0') { + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + (+M + 1) + '.0.0' + } + } + + debug('caret return', ret) + return ret + }) +} + +function replaceXRanges (comp, options) { + debug('replaceXRanges', comp, options) + return comp.split(/\s+/).map(function (comp) { + return replaceXRange(comp, options) + }).join(' ') +} + +function replaceXRange (comp, options) { + comp = comp.trim() + var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] + return comp.replace(r, function (ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + var xM = isX(M) + var xm = xM || isX(m) + var xp = xm || isX(p) + var anyX = xp + + if (gtlt === '=' && anyX) { + gtlt = '' + } + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0' + } else { + // nothing is forbidden + ret = '*' + } + } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. + // replace X with 0 + if (xm) { + m = 0 + } + p = 0 + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + // >1.2.3 => >= 1.2.4 + gtlt = '>=' + if (xm) { + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 + } + } + + ret = gtlt + M + '.' + m + '.' + p + } else if (xm) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (xp) { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } + + debug('xRange return', ret) + + return ret + }) +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars (comp, options) { + debug('replaceStars', comp, options) + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], '') +} + +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +function hyphenReplace ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = '>=' + fM + '.0.0' + } else if (isX(fp)) { + from = '>=' + fM + '.' + fm + '.0' + } else { + from = '>=' + from + } + + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = '<' + (+tM + 1) + '.0.0' + } else if (isX(tp)) { + to = '<' + tM + '.' + (+tm + 1) + '.0' + } else if (tpr) { + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr + } else { + to = '<=' + to + } + + return (from + ' ' + to).trim() +} + +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function (version) { + if (!version) { + return false + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true + } + } + return false +} + +function testSet (set, version, options) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false + } + } + + if (version.prerelease.length && !options.includePrerelease) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === ANY) { + continue + } + + if (set[i].semver.prerelease.length > 0) { + var allowed = set[i].semver + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) { + return true + } + } + } + + // Version has a -pre, but it's not one of the ones we like. + return false + } + + return true +} + +exports.satisfies = satisfies +function satisfies (version, range, options) { + try { + range = new Range(range, options) + } catch (er) { + return false + } + return range.test(version) +} + +exports.maxSatisfying = maxSatisfying +function maxSatisfying (versions, range, options) { + var max = null + var maxSV = null + try { + var rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) + } + } + }) + return max +} + +exports.minSatisfying = minSatisfying +function minSatisfying (versions, range, options) { + var min = null + var minSV = null + try { + var rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) + } + } + }) + return min +} + +exports.minVersion = minVersion +function minVersion (range, loose) { + range = new Range(range, loose) + + var minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver + } + + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver + } + + minver = null + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + comparators.forEach(function (comparator) { + // Clone to avoid manipulating the comparator's semver object. + var compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!minver || gt(minver, compver)) { + minver = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error('Unexpected operation: ' + comparator.operator) + } + }) + } + + if (minver && range.test(minver)) { + return minver + } + + return null +} + +exports.validRange = validRange +function validRange (range, options) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, options).range || '*' + } catch (er) { + return null + } +} + +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr +function ltr (version, range, options) { + return outside(version, range, '<', options) +} + +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr +function gtr (version, range, options) { + return outside(version, range, '>', options) +} + +exports.outside = outside +function outside (version, range, hilo, options) { + version = new SemVer(version, options) + range = new Range(range, options) + + var gtfn, ltefn, ltfn, comp, ecomp + switch (hilo) { + case '>': + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break + case '<': + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break + default: + throw new TypeError('Must provide a hilo val of "<" or ">"') + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, options)) { + return false + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + var high = null + var low = null + + comparators.forEach(function (comparator) { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator + } + }) + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false + } + } + return true +} + +exports.prerelease = prerelease +function prerelease (version, options) { + var parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null +} + +exports.intersects = intersects +function intersects (r1, r2, options) { + r1 = new Range(r1, options) + r2 = new Range(r2, options) + return r1.intersects(r2) +} + +exports.coerce = coerce +function coerce (version) { + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + var match = version.match(re[COERCE]) + + if (match == null) { + return null + } + + return parse(match[1] + + '.' + (match[2] || '0') + + '.' + (match[3] || '0')) +} + + +/***/ }), + +/***/ 611: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseDisplayNameEmail = exports.randomString = exports.secondsSinceEpoch = exports.getRemoteDetail = exports.getRepoPath = exports.getStringAsArray = exports.getInputAsArray = void 0; +const core = __importStar(__webpack_require__(470)); +const path = __importStar(__webpack_require__(622)); +function getInputAsArray(name, options) { + return getStringAsArray(core.getInput(name, options)); +} +exports.getInputAsArray = getInputAsArray; +function getStringAsArray(str) { + return str + .split(/[\n,]+/) + .map(s => s.trim()) + .filter(x => x !== ''); +} +exports.getStringAsArray = getStringAsArray; +function getRepoPath(relativePath) { + let githubWorkspacePath = process.env['GITHUB_WORKSPACE']; + if (!githubWorkspacePath) { + throw new Error('GITHUB_WORKSPACE not defined'); + } + githubWorkspacePath = path.resolve(githubWorkspacePath); + core.debug(`githubWorkspacePath: ${githubWorkspacePath}`); + let repoPath = githubWorkspacePath; + if (relativePath) + repoPath = path.resolve(repoPath, relativePath); + core.debug(`repoPath: ${repoPath}`); + return repoPath; +} +exports.getRepoPath = getRepoPath; +function getRemoteDetail(remoteUrl) { + // Parse the protocol and github repository from a URL + // e.g. HTTPS, peter-evans/create-pull-request + const httpsUrlPattern = /^https:\/\/.*@?github.com\/(.+\/.+)$/i; + const sshUrlPattern = /^git@github.com:(.+\/.+).git$/i; + const httpsMatch = remoteUrl.match(httpsUrlPattern); + if (httpsMatch) { + return { + protocol: 'HTTPS', + repository: httpsMatch[1] + }; + } + const sshMatch = remoteUrl.match(sshUrlPattern); + if (sshMatch) { + return { + protocol: 'SSH', + repository: sshMatch[1] + }; + } + throw new Error(`The format of '${remoteUrl}' is not a valid GitHub repository URL`); +} +exports.getRemoteDetail = getRemoteDetail; +function secondsSinceEpoch() { + const now = new Date(); + return Math.round(now.getTime() / 1000); +} +exports.secondsSinceEpoch = secondsSinceEpoch; +function randomString() { + return Math.random().toString(36).substr(2, 7); +} +exports.randomString = randomString; +function parseDisplayNameEmail(displayNameEmail) { + // Parse the name and email address from a string in the following format + // Display Name + const pattern = /^([^<]+)\s*<([^>]+)>$/i; + // Check we have a match + const match = displayNameEmail.match(pattern); + if (!match) { + throw new Error(`The format of '${displayNameEmail}' is not a valid email address with display name`); + } + // Check that name and email are not just whitespace + const name = match[1].trim(); + const email = match[2].trim(); + if (!name || !email) { + throw new Error(`The format of '${displayNameEmail}' is not a valid email address with display name`); + } + return { + name: name, + email: email + }; +} +exports.parseDisplayNameEmail = parseDisplayNameEmail; + + +/***/ }), + +/***/ 614: +/***/ (function(module) { + +module.exports = require("events"); + +/***/ }), + +/***/ 621: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const path = __webpack_require__(622); +const pathKey = __webpack_require__(682); + +module.exports = opts => { + opts = Object.assign({ + cwd: process.cwd(), + path: process.env[pathKey()] + }, opts); + + let prev; + let pth = path.resolve(opts.cwd); + const ret = []; + + while (prev !== pth) { + ret.push(path.join(pth, 'node_modules/.bin')); + prev = pth; + pth = path.resolve(pth, '..'); + } + + // ensure the running `node` binary is used + ret.push(path.dirname(process.execPath)); + + return ret.concat(opts.path).join(path.delimiter); +}; + +module.exports.env = opts => { + opts = Object.assign({ + env: process.env + }, opts); + + const env = Object.assign({}, opts.env); + const path = pathKey({env}); + + opts.path = env[path]; + env[path] = module.exports(opts); + + return env; +}; + + +/***/ }), + +/***/ 622: +/***/ (function(module) { + +module.exports = require("path"); + +/***/ }), + +/***/ 626: +/***/ (function(module) { + +"use strict"; + + +/*! + * isobject + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +function isObject(val) { + return val != null && typeof val === 'object' && Array.isArray(val) === false; +} + +/*! + * is-plain-object + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +function isObjectObject(o) { + return isObject(o) === true + && Object.prototype.toString.call(o) === '[object Object]'; +} + +function isPlainObject(o) { + var ctor,prot; + + if (isObjectObject(o) === false) return false; + + // If has modified constructor + ctor = o.constructor; + if (typeof ctor !== 'function') return false; + + // If has modified prototype + prot = ctor.prototype; + if (isObjectObject(prot) === false) return false; + + // If constructor does not have an Object-specific method + if (prot.hasOwnProperty('isPrototypeOf') === false) { + return false; + } + + // Most likely a plain Object + return true; +} + +module.exports = isPlainObject; + + +/***/ }), + +/***/ 654: +/***/ (function(module) { + +// This is not the set of all possible signals. +// +// It IS, however, the set of all signals that trigger +// an exit on either Linux or BSD systems. Linux is a +// superset of the signal names supported on BSD, and +// the unknown signals just fail to register, so we can +// catch that easily enough. +// +// Don't bother with SIGKILL. It's uncatchable, which +// means that we can't fire any callbacks anyway. +// +// If a user does happen to register a handler on a non- +// fatal signal like SIGWINCH or something, and then +// exit, it'll end up firing `process.emit('exit')`, so +// the handler will be fired anyway. +// +// SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised +// artificially, inherently leave the process in a +// state from which it is not safe to try and enter JS +// listeners. +module.exports = [ + 'SIGABRT', + 'SIGALRM', + 'SIGHUP', + 'SIGINT', + 'SIGTERM' +] + +if (process.platform !== 'win32') { + module.exports.push( + 'SIGVTALRM', + 'SIGXCPU', + 'SIGXFSZ', + 'SIGUSR2', + 'SIGTRAP', + 'SIGSYS', + 'SIGQUIT', + 'SIGIOT' + // should detect profiler and enable/disable accordingly. + // see #21 + // 'SIGPROF' + ) +} + +if (process.platform === 'linux') { + module.exports.push( + 'SIGIO', + 'SIGPOLL', + 'SIGPWR', + 'SIGSTKFLT', + 'SIGUNUSED' + ) +} + + +/***/ }), + +/***/ 669: +/***/ (function(module) { + +module.exports = require("util"); + +/***/ }), + +/***/ 672: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var _a; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert_1 = __webpack_require__(357); +const fs = __webpack_require__(747); +const path = __webpack_require__(622); +_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; +exports.IS_WINDOWS = process.platform === 'win32'; +function exists(fsPath) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exports.stat(fsPath); + } + catch (err) { + if (err.code === 'ENOENT') { + return false; + } + throw err; + } + return true; + }); +} +exports.exists = exists; +function isDirectory(fsPath, useStat = false) { + return __awaiter(this, void 0, void 0, function* () { + const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); + return stats.isDirectory(); + }); +} +exports.isDirectory = isDirectory; +/** + * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: + * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). + */ +function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (exports.IS_WINDOWS) { + return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello + ); // e.g. C: or C:\hello + } + return p.startsWith('/'); +} +exports.isRooted = isRooted; +/** + * Recursively create a directory at `fsPath`. + * + * This implementation is optimistic, meaning it attempts to create the full + * path first, and backs up the path stack from there. + * + * @param fsPath The path to create + * @param maxDepth The maximum recursion depth + * @param depth The current recursion depth + */ +function mkdirP(fsPath, maxDepth = 1000, depth = 1) { + return __awaiter(this, void 0, void 0, function* () { + assert_1.ok(fsPath, 'a path argument must be provided'); + fsPath = path.resolve(fsPath); + if (depth >= maxDepth) + return exports.mkdir(fsPath); + try { + yield exports.mkdir(fsPath); + return; + } + catch (err) { + switch (err.code) { + case 'ENOENT': { + yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1); + yield exports.mkdir(fsPath); + return; + } + default: { + let stats; + try { + stats = yield exports.stat(fsPath); + } + catch (err2) { + throw err; + } + if (!stats.isDirectory()) + throw err; + } + } + } + }); +} +exports.mkdirP = mkdirP; +/** + * Best effort attempt to determine whether a file exists and is executable. + * @param filePath file path to check + * @param extensions additional file extensions to try + * @return if file exists and is executable, returns the file path. otherwise empty string. + */ +function tryGetExecutablePath(filePath, extensions) { + return __awaiter(this, void 0, void 0, function* () { + let stats = undefined; + try { + // test file exists + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // on Windows, test for valid extension + const upperExt = path.extname(filePath).toUpperCase(); + if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + // try each extension + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = undefined; + try { + stats = yield exports.stat(filePath); + } + catch (err) { + if (err.code !== 'ENOENT') { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (exports.IS_WINDOWS) { + // preserve the case of the actual file (since an extension was appended) + try { + const directory = path.dirname(filePath); + const upperName = path.basename(filePath).toUpperCase(); + for (const actualName of yield exports.readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path.join(directory, actualName); + break; + } + } + } + catch (err) { + // eslint-disable-next-line no-console + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } + else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ''; + }); +} +exports.tryGetExecutablePath = tryGetExecutablePath; +function normalizeSeparators(p) { + p = p || ''; + if (exports.IS_WINDOWS) { + // convert slashes on Windows + p = p.replace(/\//g, '\\'); + // remove redundant slashes + return p.replace(/\\\\+/g, '\\'); + } + // remove redundant slashes + return p.replace(/\/\/+/g, '/'); +} +// on Mac/Linux, test the execute bit +// R W X R W X R W X +// 256 128 64 32 16 8 4 2 1 +function isUnixExecutable(stats) { + return ((stats.mode & 1) > 0 || + ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || + ((stats.mode & 64) > 0 && stats.uid === process.getuid())); +} +//# sourceMappingURL=io-util.js.map + +/***/ }), + +/***/ 682: +/***/ (function(module) { + +"use strict"; + +module.exports = opts => { + opts = opts || {}; + + const env = opts.env || process.env; + const platform = opts.platform || process.platform; + + if (platform !== 'win32') { + return 'PATH'; + } + + return Object.keys(env).find(x => x.toUpperCase() === 'PATH') || 'Path'; +}; + + +/***/ }), + +/***/ 686: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; @@ -947,367 +7947,58 @@ class ExecState extends events.EventEmitter { /***/ }), -/***/ 16: -/***/ (function(module) { - -module.exports = require("tls"); - -/***/ }), - -/***/ 57: -/***/ (function(__unusedmodule, exports, __webpack_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.isDocker = void 0; -const fs = __importStar(__webpack_require__(747)); -function hasDockerEnv() { - try { - fs.statSync('/.dockerenv'); - return true; - } - catch (_) { - return false; - } -} -function hasDockerCGroup() { - try { - return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker'); - } - catch (_) { - return false; - } -} -function isDocker() { - return hasDockerEnv() || hasDockerCGroup(); -} -exports.isDocker = isDocker; - - -/***/ }), - -/***/ 87: -/***/ (function(module) { - -module.exports = require("os"); - -/***/ }), - -/***/ 129: -/***/ (function(module) { - -module.exports = require("child_process"); - -/***/ }), - -/***/ 139: -/***/ (function(module, __unusedexports, __webpack_require__) { - -// Unique ID creation requires a high quality random # generator. In node.js -// this is pretty straight-forward - we use the crypto API. - -var crypto = __webpack_require__(417); - -module.exports = function nodeRNG() { - return crypto.randomBytes(16); -}; - - -/***/ }), - -/***/ 141: -/***/ (function(__unusedmodule, exports, __webpack_require__) { +/***/ 692: +/***/ (function(__unusedmodule, exports) { "use strict"; -var net = __webpack_require__(631); -var tls = __webpack_require__(16); -var http = __webpack_require__(605); -var https = __webpack_require__(211); -var events = __webpack_require__(614); -var assert = __webpack_require__(357); -var util = __webpack_require__(669); +Object.defineProperty(exports, '__esModule', { value: true }); +class Deprecation extends Error { + constructor(message) { + super(message); // Maintains proper stack trace (only available on V8) -exports.httpOverHttp = httpOverHttp; -exports.httpsOverHttp = httpsOverHttp; -exports.httpOverHttps = httpOverHttps; -exports.httpsOverHttps = httpsOverHttps; + /* istanbul ignore next */ - -function httpOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - return agent; -} - -function httpsOverHttp(options) { - var agent = new TunnelingAgent(options); - agent.request = http.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} - -function httpOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - return agent; -} - -function httpsOverHttps(options) { - var agent = new TunnelingAgent(options); - agent.request = https.request; - agent.createSocket = createSecureSocket; - agent.defaultPort = 443; - return agent; -} - - -function TunnelingAgent(options) { - var self = this; - self.options = options || {}; - self.proxyOptions = self.options.proxy || {}; - self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; - self.requests = []; - self.sockets = []; - - self.on('free', function onFree(socket, host, port, localAddress) { - var options = toOptions(host, port, localAddress); - for (var i = 0, len = self.requests.length; i < len; ++i) { - var pending = self.requests[i]; - if (pending.host === options.host && pending.port === options.port) { - // Detect the request to connect same origin server, - // reuse the connection. - self.requests.splice(i, 1); - pending.request.onSocket(socket); - return; - } - } - socket.destroy(); - self.removeSocket(socket); - }); -} -util.inherits(TunnelingAgent, events.EventEmitter); - -TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { - var self = this; - var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); - - if (self.sockets.length >= this.maxSockets) { - // We are over limit so we'll add it to the queue. - self.requests.push(options); - return; - } - - // If we are under maxSockets create a new one. - self.createSocket(options, function(socket) { - socket.on('free', onFree); - socket.on('close', onCloseOrRemove); - socket.on('agentRemove', onCloseOrRemove); - req.onSocket(socket); - - function onFree() { - self.emit('free', socket, options); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); } - function onCloseOrRemove(err) { - self.removeSocket(socket); - socket.removeListener('free', onFree); - socket.removeListener('close', onCloseOrRemove); - socket.removeListener('agentRemove', onCloseOrRemove); - } - }); -}; - -TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { - var self = this; - var placeholder = {}; - self.sockets.push(placeholder); - - var connectOptions = mergeOptions({}, self.proxyOptions, { - method: 'CONNECT', - path: options.host + ':' + options.port, - agent: false, - headers: { - host: options.host + ':' + options.port - } - }); - if (options.localAddress) { - connectOptions.localAddress = options.localAddress; - } - if (connectOptions.proxyAuth) { - connectOptions.headers = connectOptions.headers || {}; - connectOptions.headers['Proxy-Authorization'] = 'Basic ' + - new Buffer(connectOptions.proxyAuth).toString('base64'); + this.name = 'Deprecation'; } - debug('making CONNECT request'); - var connectReq = self.request(connectOptions); - connectReq.useChunkedEncodingByDefault = false; // for v0.6 - connectReq.once('response', onResponse); // for v0.6 - connectReq.once('upgrade', onUpgrade); // for v0.6 - connectReq.once('connect', onConnect); // for v0.7 or later - connectReq.once('error', onError); - connectReq.end(); - - function onResponse(res) { - // Very hacky. This is necessary to avoid http-parser leaks. - res.upgrade = true; - } - - function onUpgrade(res, socket, head) { - // Hacky. - process.nextTick(function() { - onConnect(res, socket, head); - }); - } - - function onConnect(res, socket, head) { - connectReq.removeAllListeners(); - socket.removeAllListeners(); - - if (res.statusCode !== 200) { - debug('tunneling socket could not be established, statusCode=%d', - res.statusCode); - socket.destroy(); - var error = new Error('tunneling socket could not be established, ' + - 'statusCode=' + res.statusCode); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - if (head.length > 0) { - debug('got illegal response body from proxy'); - socket.destroy(); - var error = new Error('got illegal response body from proxy'); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - return; - } - debug('tunneling connection has established'); - self.sockets[self.sockets.indexOf(placeholder)] = socket; - return cb(socket); - } - - function onError(cause) { - connectReq.removeAllListeners(); - - debug('tunneling socket could not be established, cause=%s\n', - cause.message, cause.stack); - var error = new Error('tunneling socket could not be established, ' + - 'cause=' + cause.message); - error.code = 'ECONNRESET'; - options.request.emit('error', error); - self.removeSocket(placeholder); - } -}; - -TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { - var pos = this.sockets.indexOf(socket) - if (pos === -1) { - return; - } - this.sockets.splice(pos, 1); - - var pending = this.requests.shift(); - if (pending) { - // If we have pending requests and a socket gets closed a new one - // needs to be created to take over in the pool for the one that closed. - this.createSocket(pending, function(socket) { - pending.request.onSocket(socket); - }); - } -}; - -function createSecureSocket(options, cb) { - var self = this; - TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { - var hostHeader = options.request.getHeader('host'); - var tlsOptions = mergeOptions({}, self.options, { - socket: socket, - servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host - }); - - // 0 is dummy port for v0.6 - var secureSocket = tls.connect(0, tlsOptions); - self.sockets[self.sockets.indexOf(socket)] = secureSocket; - cb(secureSocket); - }); } - -function toOptions(host, port, localAddress) { - if (typeof host === 'string') { // since v0.10 - return { - host: host, - port: port, - localAddress: localAddress - }; - } - return host; // for v0.11 or later -} - -function mergeOptions(target) { - for (var i = 1, len = arguments.length; i < len; ++i) { - var overrides = arguments[i]; - if (typeof overrides === 'object') { - var keys = Object.keys(overrides); - for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { - var k = keys[j]; - if (overrides[k] !== undefined) { - target[k] = overrides[k]; - } - } - } - } - return target; -} - - -var debug; -if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { - debug = function() { - var args = Array.prototype.slice.call(arguments); - if (typeof args[0] === 'string') { - args[0] = 'TUNNEL: ' + args[0]; - } else { - args.unshift('TUNNEL:'); - } - console.error.apply(console, args); - } -} else { - debug = function() {}; -} -exports.debug = debug; // for test +exports.Deprecation = Deprecation; /***/ }), -/***/ 198: +/***/ 697: +/***/ (function(module) { + +"use strict"; + +module.exports = (promise, onFinally) => { + onFinally = onFinally || (() => {}); + + return promise.then( + val => new Promise(resolve => { + resolve(onFinally()); + }).then(() => val), + err => new Promise(resolve => { + resolve(onFinally()); + }).then(() => { + throw err; + }) + ); +}; + + +/***/ }), + +/***/ 718: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; @@ -1341,3313 +8032,132 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", { value: true }); +exports.GitHubHelper = void 0; const core = __importStar(__webpack_require__(470)); -const exec = __importStar(__webpack_require__(986)); -const isDocker_1 = __webpack_require__(57); -const setupPython_1 = __webpack_require__(953); -const git_1 = __webpack_require__(453); -const util_1 = __webpack_require__(669); -const EXTRAHEADER_OPTION = 'http.https://github.com/.extraheader'; -const EXTRAHEADER_VALUE_REGEX = '^AUTHORIZATION:'; -function run() { - return __awaiter(this, void 0, void 0, function* () { - let repoPath; - let extraHeaderOption = new git_1.ConfigOption(); - try { - // Python assets - const cpr = `${__dirname}/cpr`; - core.debug(`cpr: ${cpr}`); - // Determine how to access python and pip - const { pip, python } = (function () { - if (isDocker_1.isDocker()) { - core.info('Running inside a Docker container'); - // Python 3 assumed to be installed and on the PATH - return { - pip: 'pip3', - python: 'python3' - }; - } - else { - // Setup Python from the tool cache - setupPython_1.setupPython('3.x', 'x64'); - return { - pip: 'pip', - python: 'python' - }; - } - })(); - // Install requirements - yield exec.exec(pip, [ - 'install', - '--requirement', - `${cpr}/requirements.txt`, - '--no-index', - `--find-links=${__dirname}/vendor` - ]); - // Fetch action inputs - const inputs = { - token: core.getInput('token'), - path: core.getInput('path'), - commitMessage: core.getInput('commit-message'), - committer: core.getInput('committer'), - author: core.getInput('author'), - title: core.getInput('title'), - body: core.getInput('body'), - labels: core.getInput('labels'), - assignees: core.getInput('assignees'), - reviewers: core.getInput('reviewers'), - teamReviewers: core.getInput('team-reviewers'), - milestone: core.getInput('milestone'), - project: core.getInput('project'), - projectColumn: core.getInput('project-column'), - draft: core.getInput('draft'), - branch: core.getInput('branch'), - requestToParent: core.getInput('request-to-parent'), - base: core.getInput('base'), - branchSuffix: core.getInput('branch-suffix') - }; - core.debug(`Inputs: ${util_1.inspect(inputs)}`); - // Set environment variables from inputs. - if (inputs.token) - process.env.GITHUB_TOKEN = inputs.token; - if (inputs.path) - process.env.CPR_PATH = inputs.path; - if (inputs.commitMessage) - process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage; - if (inputs.committer) - process.env.CPR_COMMITTER = inputs.committer; - if (inputs.author) - process.env.CPR_AUTHOR = inputs.author; - if (inputs.title) - process.env.CPR_TITLE = inputs.title; - if (inputs.body) - process.env.CPR_BODY = inputs.body; - if (inputs.labels) - process.env.CPR_LABELS = inputs.labels; - if (inputs.assignees) - process.env.CPR_ASSIGNEES = inputs.assignees; - if (inputs.reviewers) - process.env.CPR_REVIEWERS = inputs.reviewers; - if (inputs.teamReviewers) - process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers; - if (inputs.milestone) - process.env.CPR_MILESTONE = inputs.milestone; - if (inputs.project) - process.env.CPR_PROJECT_NAME = inputs.project; - if (inputs.projectColumn) - process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn; - if (inputs.draft) - process.env.CPR_DRAFT = inputs.draft; - if (inputs.branch) - process.env.CPR_BRANCH = inputs.branch; - if (inputs.requestToParent) - process.env.CPR_REQUEST_TO_PARENT = inputs.requestToParent; - if (inputs.base) - process.env.CPR_BASE = inputs.base; - if (inputs.branchSuffix) - process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix; - // Get the repository path - repoPath = git_1.getRepoPath(inputs.path); - // Get the extraheader config option if it exists - extraHeaderOption = yield git_1.getAndUnsetConfigOption(repoPath, EXTRAHEADER_OPTION, EXTRAHEADER_VALUE_REGEX); - // Execute create pull request - yield exec.exec(python, [`${cpr}/create_pull_request.py`]); +const octokit_client_1 = __webpack_require__(921); +const ERROR_PR_REVIEW_FROM_AUTHOR = 'Review cannot be requested from pull request author'; +class GitHubHelper { + constructor(token) { + const options = {}; + if (token) { + options.auth = `${token}`; } - catch (error) { - core.setFailed(error.message); - } - finally { - // Restore the extraheader config option - if (extraHeaderOption.value != '') { - if (yield git_1.addConfigOption(repoPath, EXTRAHEADER_OPTION, extraHeaderOption.value)) - core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`); - } - } - }); -} -run(); - - -/***/ }), - -/***/ 211: -/***/ (function(module) { - -module.exports = require("https"); - -/***/ }), - -/***/ 280: -/***/ (function(module, exports) { - -exports = module.exports = SemVer - -var debug -/* istanbul ignore next */ -if (typeof process === 'object' && - process.env && - process.env.NODE_DEBUG && - /\bsemver\b/i.test(process.env.NODE_DEBUG)) { - debug = function () { - var args = Array.prototype.slice.call(arguments, 0) - args.unshift('SEMVER') - console.log.apply(console, args) - } -} else { - debug = function () {} -} - -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0' - -var MAX_LENGTH = 256 -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || - /* istanbul ignore next */ 9007199254740991 - -// Max safe segment length for coercion. -var MAX_SAFE_COMPONENT_LENGTH = 16 - -// The actual regexps go on exports.re -var re = exports.re = [] -var src = exports.src = [] -var t = exports.tokens = {} -var R = 0 - -function tok (n) { - t[n] = R++ -} - -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. - -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. - -tok('NUMERICIDENTIFIER') -src[t.NUMERICIDENTIFIER] = '0|[1-9]\\d*' -tok('NUMERICIDENTIFIERLOOSE') -src[t.NUMERICIDENTIFIERLOOSE] = '[0-9]+' - -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. - -tok('NONNUMERICIDENTIFIER') -src[t.NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' - -// ## Main Version -// Three dot-separated numeric identifiers. - -tok('MAINVERSION') -src[t.MAINVERSION] = '(' + src[t.NUMERICIDENTIFIER] + ')\\.' + - '(' + src[t.NUMERICIDENTIFIER] + ')\\.' + - '(' + src[t.NUMERICIDENTIFIER] + ')' - -tok('MAINVERSIONLOOSE') -src[t.MAINVERSIONLOOSE] = '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[t.NUMERICIDENTIFIERLOOSE] + ')' - -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. - -tok('PRERELEASEIDENTIFIER') -src[t.PRERELEASEIDENTIFIER] = '(?:' + src[t.NUMERICIDENTIFIER] + - '|' + src[t.NONNUMERICIDENTIFIER] + ')' - -tok('PRERELEASEIDENTIFIERLOOSE') -src[t.PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[t.NUMERICIDENTIFIERLOOSE] + - '|' + src[t.NONNUMERICIDENTIFIER] + ')' - -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. - -tok('PRERELEASE') -src[t.PRERELEASE] = '(?:-(' + src[t.PRERELEASEIDENTIFIER] + - '(?:\\.' + src[t.PRERELEASEIDENTIFIER] + ')*))' - -tok('PRERELEASELOOSE') -src[t.PRERELEASELOOSE] = '(?:-?(' + src[t.PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[t.PRERELEASEIDENTIFIERLOOSE] + ')*))' - -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. - -tok('BUILDIDENTIFIER') -src[t.BUILDIDENTIFIER] = '[0-9A-Za-z-]+' - -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. - -tok('BUILD') -src[t.BUILD] = '(?:\\+(' + src[t.BUILDIDENTIFIER] + - '(?:\\.' + src[t.BUILDIDENTIFIER] + ')*))' - -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. - -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. - -tok('FULL') -tok('FULLPLAIN') -src[t.FULLPLAIN] = 'v?' + src[t.MAINVERSION] + - src[t.PRERELEASE] + '?' + - src[t.BUILD] + '?' - -src[t.FULL] = '^' + src[t.FULLPLAIN] + '$' - -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -tok('LOOSEPLAIN') -src[t.LOOSEPLAIN] = '[v=\\s]*' + src[t.MAINVERSIONLOOSE] + - src[t.PRERELEASELOOSE] + '?' + - src[t.BUILD] + '?' - -tok('LOOSE') -src[t.LOOSE] = '^' + src[t.LOOSEPLAIN] + '$' - -tok('GTLT') -src[t.GTLT] = '((?:<|>)?=?)' - -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -tok('XRANGEIDENTIFIERLOOSE') -src[t.XRANGEIDENTIFIERLOOSE] = src[t.NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' -tok('XRANGEIDENTIFIER') -src[t.XRANGEIDENTIFIER] = src[t.NUMERICIDENTIFIER] + '|x|X|\\*' - -tok('XRANGEPLAIN') -src[t.XRANGEPLAIN] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[t.XRANGEIDENTIFIER] + ')' + - '(?:' + src[t.PRERELEASE] + ')?' + - src[t.BUILD] + '?' + - ')?)?' - -tok('XRANGEPLAINLOOSE') -src[t.XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[t.XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[t.PRERELEASELOOSE] + ')?' + - src[t.BUILD] + '?' + - ')?)?' - -tok('XRANGE') -src[t.XRANGE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAIN] + '$' -tok('XRANGELOOSE') -src[t.XRANGELOOSE] = '^' + src[t.GTLT] + '\\s*' + src[t.XRANGEPLAINLOOSE] + '$' - -// Coercion. -// Extract anything that could conceivably be a part of a valid semver -tok('COERCE') -src[t.COERCE] = '(^|[^\\d])' + - '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + - '(?:$|[^\\d])' -tok('COERCERTL') -re[t.COERCERTL] = new RegExp(src[t.COERCE], 'g') - -// Tilde ranges. -// Meaning is "reasonably at or greater than" -tok('LONETILDE') -src[t.LONETILDE] = '(?:~>?)' - -tok('TILDETRIM') -src[t.TILDETRIM] = '(\\s*)' + src[t.LONETILDE] + '\\s+' -re[t.TILDETRIM] = new RegExp(src[t.TILDETRIM], 'g') -var tildeTrimReplace = '$1~' - -tok('TILDE') -src[t.TILDE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAIN] + '$' -tok('TILDELOOSE') -src[t.TILDELOOSE] = '^' + src[t.LONETILDE] + src[t.XRANGEPLAINLOOSE] + '$' - -// Caret ranges. -// Meaning is "at least and backwards compatible with" -tok('LONECARET') -src[t.LONECARET] = '(?:\\^)' - -tok('CARETTRIM') -src[t.CARETTRIM] = '(\\s*)' + src[t.LONECARET] + '\\s+' -re[t.CARETTRIM] = new RegExp(src[t.CARETTRIM], 'g') -var caretTrimReplace = '$1^' - -tok('CARET') -src[t.CARET] = '^' + src[t.LONECARET] + src[t.XRANGEPLAIN] + '$' -tok('CARETLOOSE') -src[t.CARETLOOSE] = '^' + src[t.LONECARET] + src[t.XRANGEPLAINLOOSE] + '$' - -// A simple gt/lt/eq thing, or just "" to indicate "any version" -tok('COMPARATORLOOSE') -src[t.COMPARATORLOOSE] = '^' + src[t.GTLT] + '\\s*(' + src[t.LOOSEPLAIN] + ')$|^$' -tok('COMPARATOR') -src[t.COMPARATOR] = '^' + src[t.GTLT] + '\\s*(' + src[t.FULLPLAIN] + ')$|^$' - -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -tok('COMPARATORTRIM') -src[t.COMPARATORTRIM] = '(\\s*)' + src[t.GTLT] + - '\\s*(' + src[t.LOOSEPLAIN] + '|' + src[t.XRANGEPLAIN] + ')' - -// this one has to use the /g flag -re[t.COMPARATORTRIM] = new RegExp(src[t.COMPARATORTRIM], 'g') -var comparatorTrimReplace = '$1$2$3' - -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -tok('HYPHENRANGE') -src[t.HYPHENRANGE] = '^\\s*(' + src[t.XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[t.XRANGEPLAIN] + ')' + - '\\s*$' - -tok('HYPHENRANGELOOSE') -src[t.HYPHENRANGELOOSE] = '^\\s*(' + src[t.XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[t.XRANGEPLAINLOOSE] + ')' + - '\\s*$' - -// Star ranges basically just allow anything at all. -tok('STAR') -src[t.STAR] = '(<|>)?=?\\s*\\*' - -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]) - if (!re[i]) { - re[i] = new RegExp(src[i]) - } -} - -exports.parse = parse -function parse (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false + this.octokit = new octokit_client_1.Octokit(options); } - } - - if (version instanceof SemVer) { - return version - } - - if (typeof version !== 'string') { - return null - } - - if (version.length > MAX_LENGTH) { - return null - } - - var r = options.loose ? re[t.LOOSE] : re[t.FULL] - if (!r.test(version)) { - return null - } - - try { - return new SemVer(version, options) - } catch (er) { - return null - } -} - -exports.valid = valid -function valid (version, options) { - var v = parse(version, options) - return v ? v.version : null -} - -exports.clean = clean -function clean (version, options) { - var s = parse(version.trim().replace(/^[=v]+/, ''), options) - return s ? s.version : null -} - -exports.SemVer = SemVer - -function SemVer (version, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - if (version instanceof SemVer) { - if (version.loose === options.loose) { - return version - } else { - version = version.version - } - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version) - } - - if (version.length > MAX_LENGTH) { - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') - } - - if (!(this instanceof SemVer)) { - return new SemVer(version, options) - } - - debug('SemVer', version, options) - this.options = options - this.loose = !!options.loose - - var m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) - - if (!m) { - throw new TypeError('Invalid Version: ' + version) - } - - this.raw = version - - // these are actually numbers - this.major = +m[1] - this.minor = +m[2] - this.patch = +m[3] - - if (this.major > MAX_SAFE_INTEGER || this.major < 0) { - throw new TypeError('Invalid major version') - } - - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { - throw new TypeError('Invalid minor version') - } - - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { - throw new TypeError('Invalid patch version') - } - - // numberify any prerelease numeric ids - if (!m[4]) { - this.prerelease = [] - } else { - this.prerelease = m[4].split('.').map(function (id) { - if (/^[0-9]+$/.test(id)) { - var num = +id - if (num >= 0 && num < MAX_SAFE_INTEGER) { - return num - } - } - return id - }) - } - - this.build = m[5] ? m[5].split('.') : [] - this.format() -} - -SemVer.prototype.format = function () { - this.version = this.major + '.' + this.minor + '.' + this.patch - if (this.prerelease.length) { - this.version += '-' + this.prerelease.join('.') - } - return this.version -} - -SemVer.prototype.toString = function () { - return this.version -} - -SemVer.prototype.compare = function (other) { - debug('SemVer.compare', this.version, this.options, other) - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return this.compareMain(other) || this.comparePre(other) -} - -SemVer.prototype.compareMain = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch) -} - -SemVer.prototype.comparePre = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) { - return -1 - } else if (!this.prerelease.length && other.prerelease.length) { - return 1 - } else if (!this.prerelease.length && !other.prerelease.length) { - return 0 - } - - var i = 0 - do { - var a = this.prerelease[i] - var b = other.prerelease[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) -} - -SemVer.prototype.compareBuild = function (other) { - if (!(other instanceof SemVer)) { - other = new SemVer(other, this.options) - } - - var i = 0 - do { - var a = this.build[i] - var b = other.build[i] - debug('prerelease compare', i, a, b) - if (a === undefined && b === undefined) { - return 0 - } else if (b === undefined) { - return 1 - } else if (a === undefined) { - return -1 - } else if (a === b) { - continue - } else { - return compareIdentifiers(a, b) - } - } while (++i) -} - -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function (release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0 - this.patch = 0 - this.minor = 0 - this.major++ - this.inc('pre', identifier) - break - case 'preminor': - this.prerelease.length = 0 - this.patch = 0 - this.minor++ - this.inc('pre', identifier) - break - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0 - this.inc('patch', identifier) - this.inc('pre', identifier) - break - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) { - this.inc('patch', identifier) - } - this.inc('pre', identifier) - break - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || - this.patch !== 0 || - this.prerelease.length === 0) { - this.major++ - } - this.minor = 0 - this.patch = 0 - this.prerelease = [] - break - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) { - this.minor++ - } - this.patch = 0 - this.prerelease = [] - break - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) { - this.patch++ - } - this.prerelease = [] - break - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) { - this.prerelease = [0] - } else { - var i = this.prerelease.length - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++ - i = -2 - } - } - if (i === -1) { - // didn't increment anything - this.prerelease.push(0) - } - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) { - this.prerelease = [identifier, 0] - } - } else { - this.prerelease = [identifier, 0] - } - } - break - - default: - throw new Error('invalid increment argument: ' + release) - } - this.format() - this.raw = this.version - return this -} - -exports.inc = inc -function inc (version, release, loose, identifier) { - if (typeof (loose) === 'string') { - identifier = loose - loose = undefined - } - - try { - return new SemVer(version, loose).inc(release, identifier).version - } catch (er) { - return null - } -} - -exports.diff = diff -function diff (version1, version2) { - if (eq(version1, version2)) { - return null - } else { - var v1 = parse(version1) - var v2 = parse(version2) - var prefix = '' - if (v1.prerelease.length || v2.prerelease.length) { - prefix = 'pre' - var defaultResult = 'prerelease' - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return prefix + key - } - } - } - return defaultResult // may be undefined - } -} - -exports.compareIdentifiers = compareIdentifiers - -var numeric = /^[0-9]+$/ -function compareIdentifiers (a, b) { - var anum = numeric.test(a) - var bnum = numeric.test(b) - - if (anum && bnum) { - a = +a - b = +b - } - - return a === b ? 0 - : (anum && !bnum) ? -1 - : (bnum && !anum) ? 1 - : a < b ? -1 - : 1 -} - -exports.rcompareIdentifiers = rcompareIdentifiers -function rcompareIdentifiers (a, b) { - return compareIdentifiers(b, a) -} - -exports.major = major -function major (a, loose) { - return new SemVer(a, loose).major -} - -exports.minor = minor -function minor (a, loose) { - return new SemVer(a, loose).minor -} - -exports.patch = patch -function patch (a, loose) { - return new SemVer(a, loose).patch -} - -exports.compare = compare -function compare (a, b, loose) { - return new SemVer(a, loose).compare(new SemVer(b, loose)) -} - -exports.compareLoose = compareLoose -function compareLoose (a, b) { - return compare(a, b, true) -} - -exports.compareBuild = compareBuild -function compareBuild (a, b, loose) { - var versionA = new SemVer(a, loose) - var versionB = new SemVer(b, loose) - return versionA.compare(versionB) || versionA.compareBuild(versionB) -} - -exports.rcompare = rcompare -function rcompare (a, b, loose) { - return compare(b, a, loose) -} - -exports.sort = sort -function sort (list, loose) { - return list.sort(function (a, b) { - return exports.compareBuild(a, b, loose) - }) -} - -exports.rsort = rsort -function rsort (list, loose) { - return list.sort(function (a, b) { - return exports.compareBuild(b, a, loose) - }) -} - -exports.gt = gt -function gt (a, b, loose) { - return compare(a, b, loose) > 0 -} - -exports.lt = lt -function lt (a, b, loose) { - return compare(a, b, loose) < 0 -} - -exports.eq = eq -function eq (a, b, loose) { - return compare(a, b, loose) === 0 -} - -exports.neq = neq -function neq (a, b, loose) { - return compare(a, b, loose) !== 0 -} - -exports.gte = gte -function gte (a, b, loose) { - return compare(a, b, loose) >= 0 -} - -exports.lte = lte -function lte (a, b, loose) { - return compare(a, b, loose) <= 0 -} - -exports.cmp = cmp -function cmp (a, op, b, loose) { - switch (op) { - case '===': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a === b - - case '!==': - if (typeof a === 'object') - a = a.version - if (typeof b === 'object') - b = b.version - return a !== b - - case '': - case '=': - case '==': - return eq(a, b, loose) - - case '!=': - return neq(a, b, loose) - - case '>': - return gt(a, b, loose) - - case '>=': - return gte(a, b, loose) - - case '<': - return lt(a, b, loose) - - case '<=': - return lte(a, b, loose) - - default: - throw new TypeError('Invalid operator: ' + op) - } -} - -exports.Comparator = Comparator -function Comparator (comp, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (comp instanceof Comparator) { - if (comp.loose === !!options.loose) { - return comp - } else { - comp = comp.value - } - } - - if (!(this instanceof Comparator)) { - return new Comparator(comp, options) - } - - debug('comparator', comp, options) - this.options = options - this.loose = !!options.loose - this.parse(comp) - - if (this.semver === ANY) { - this.value = '' - } else { - this.value = this.operator + this.semver.version - } - - debug('comp', this) -} - -var ANY = {} -Comparator.prototype.parse = function (comp) { - var r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] - var m = comp.match(r) - - if (!m) { - throw new TypeError('Invalid comparator: ' + comp) - } - - this.operator = m[1] !== undefined ? m[1] : '' - if (this.operator === '=') { - this.operator = '' - } - - // if it literally is just '>' or '' then allow anything. - if (!m[2]) { - this.semver = ANY - } else { - this.semver = new SemVer(m[2], this.options.loose) - } -} - -Comparator.prototype.toString = function () { - return this.value -} - -Comparator.prototype.test = function (version) { - debug('Comparator.test', version, this.options.loose) - - if (this.semver === ANY || version === ANY) { - return true - } - - if (typeof version === 'string') { - try { - version = new SemVer(version, this.options) - } catch (er) { - return false - } - } - - return cmp(version, this.operator, this.semver, this.options) -} - -Comparator.prototype.intersects = function (comp, options) { - if (!(comp instanceof Comparator)) { - throw new TypeError('a Comparator is required') - } - - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - var rangeTmp - - if (this.operator === '') { - if (this.value === '') { - return true - } - rangeTmp = new Range(comp.value, options) - return satisfies(this.value, rangeTmp, options) - } else if (comp.operator === '') { - if (comp.value === '') { - return true - } - rangeTmp = new Range(this.value, options) - return satisfies(comp.semver, rangeTmp, options) - } - - var sameDirectionIncreasing = - (this.operator === '>=' || this.operator === '>') && - (comp.operator === '>=' || comp.operator === '>') - var sameDirectionDecreasing = - (this.operator === '<=' || this.operator === '<') && - (comp.operator === '<=' || comp.operator === '<') - var sameSemVer = this.semver.version === comp.semver.version - var differentDirectionsInclusive = - (this.operator === '>=' || this.operator === '<=') && - (comp.operator === '>=' || comp.operator === '<=') - var oppositeDirectionsLessThan = - cmp(this.semver, '<', comp.semver, options) && - ((this.operator === '>=' || this.operator === '>') && - (comp.operator === '<=' || comp.operator === '<')) - var oppositeDirectionsGreaterThan = - cmp(this.semver, '>', comp.semver, options) && - ((this.operator === '<=' || this.operator === '<') && - (comp.operator === '>=' || comp.operator === '>')) - - return sameDirectionIncreasing || sameDirectionDecreasing || - (sameSemVer && differentDirectionsInclusive) || - oppositeDirectionsLessThan || oppositeDirectionsGreaterThan -} - -exports.Range = Range -function Range (range, options) { - if (!options || typeof options !== 'object') { - options = { - loose: !!options, - includePrerelease: false - } - } - - if (range instanceof Range) { - if (range.loose === !!options.loose && - range.includePrerelease === !!options.includePrerelease) { - return range - } else { - return new Range(range.raw, options) - } - } - - if (range instanceof Comparator) { - return new Range(range.value, options) - } - - if (!(this instanceof Range)) { - return new Range(range, options) - } - - this.options = options - this.loose = !!options.loose - this.includePrerelease = !!options.includePrerelease - - // First, split based on boolean or || - this.raw = range - this.set = range.split(/\s*\|\|\s*/).map(function (range) { - return this.parseRange(range.trim()) - }, this).filter(function (c) { - // throw out any that are not relevant for whatever reason - return c.length - }) - - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range) - } - - this.format() -} - -Range.prototype.format = function () { - this.range = this.set.map(function (comps) { - return comps.join(' ').trim() - }).join('||').trim() - return this.range -} - -Range.prototype.toString = function () { - return this.range -} - -Range.prototype.parseRange = function (range) { - var loose = this.options.loose - range = range.trim() - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE] - range = range.replace(hr, hyphenReplace) - debug('hyphen replace', range) - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) - debug('comparator trim', range, re[t.COMPARATORTRIM]) - - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[t.TILDETRIM], tildeTrimReplace) - - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[t.CARETTRIM], caretTrimReplace) - - // normalize spaces - range = range.split(/\s+/).join(' ') - - // At this point, the range is completely trimmed and - // ready to be split into comparators. - - var compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] - var set = range.split(' ').map(function (comp) { - return parseComparator(comp, this.options) - }, this).join(' ').split(/\s+/) - if (this.options.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function (comp) { - return !!comp.match(compRe) - }) - } - set = set.map(function (comp) { - return new Comparator(comp, this.options) - }, this) - - return set -} - -Range.prototype.intersects = function (range, options) { - if (!(range instanceof Range)) { - throw new TypeError('a Range is required') - } - - return this.set.some(function (thisComparators) { - return ( - isSatisfiable(thisComparators, options) && - range.set.some(function (rangeComparators) { - return ( - isSatisfiable(rangeComparators, options) && - thisComparators.every(function (thisComparator) { - return rangeComparators.every(function (rangeComparator) { - return thisComparator.intersects(rangeComparator, options) - }) - }) - ) - }) - ) - }) -} - -// take a set of comparators and determine whether there -// exists a version which can satisfy it -function isSatisfiable (comparators, options) { - var result = true - var remainingComparators = comparators.slice() - var testComparator = remainingComparators.pop() - - while (result && remainingComparators.length) { - result = remainingComparators.every(function (otherComparator) { - return testComparator.intersects(otherComparator, options) - }) - - testComparator = remainingComparators.pop() - } - - return result -} - -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators -function toComparators (range, options) { - return new Range(range, options).set.map(function (comp) { - return comp.map(function (c) { - return c.value - }).join(' ').trim().split(' ') - }) -} - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator (comp, options) { - debug('comp', comp, options) - comp = replaceCarets(comp, options) - debug('caret', comp) - comp = replaceTildes(comp, options) - debug('tildes', comp) - comp = replaceXRanges(comp, options) - debug('xrange', comp) - comp = replaceStars(comp, options) - debug('stars', comp) - return comp -} - -function isX (id) { - return !id || id.toLowerCase() === 'x' || id === '*' -} - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceTilde(comp, options) - }).join(' ') -} - -function replaceTilde (comp, options) { - var r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE] - return comp.replace(r, function (_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else if (pr) { - debug('replaceTilde pr', pr) - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } else { - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - - debug('tilde return', ret) - return ret - }) -} - -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets (comp, options) { - return comp.trim().split(/\s+/).map(function (comp) { - return replaceCaret(comp, options) - }).join(' ') -} - -function replaceCaret (comp, options) { - debug('caret', comp, options) - var r = options.loose ? re[t.CARETLOOSE] : re[t.CARET] - return comp.replace(r, function (_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr) - var ret - - if (isX(M)) { - ret = '' - } else if (isX(m)) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' - } else if (isX(p)) { - if (M === '0') { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' - } else { - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' - } - } else if (pr) { - debug('replaceCaret pr', pr) - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + M + '.' + (+m + 1) + '.0' - } - } else { - ret = '>=' + M + '.' + m + '.' + p + '-' + pr + - ' <' + (+M + 1) + '.0.0' - } - } else { - debug('no pr') - if (M === '0') { - if (m === '0') { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1) - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0' - } - } else { - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0' - } - } - - debug('caret return', ret) - return ret - }) -} - -function replaceXRanges (comp, options) { - debug('replaceXRanges', comp, options) - return comp.split(/\s+/).map(function (comp) { - return replaceXRange(comp, options) - }).join(' ') -} - -function replaceXRange (comp, options) { - comp = comp.trim() - var r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE] - return comp.replace(r, function (ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr) - var xM = isX(M) - var xm = xM || isX(m) - var xp = xm || isX(p) - var anyX = xp - - if (gtlt === '=' && anyX) { - gtlt = '' - } - - // if we're including prereleases in the match, then we need - // to fix this to -0, the lowest possible prerelease value - pr = options.includePrerelease ? '-0' : '' - - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0-0' - } else { - // nothing is forbidden - ret = '*' - } - } else if (gtlt && anyX) { - // we know patch is an x, because we have any x at all. - // replace X with 0 - if (xm) { - m = 0 - } - p = 0 - - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>=' - if (xm) { - M = +M + 1 - m = 0 - p = 0 - } else { - m = +m + 1 - p = 0 - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<' - if (xm) { - M = +M + 1 - } else { - m = +m + 1 - } - } - - ret = gtlt + M + '.' + m + '.' + p + pr - } else if (xm) { - ret = '>=' + M + '.0.0' + pr + ' <' + (+M + 1) + '.0.0' + pr - } else if (xp) { - ret = '>=' + M + '.' + m + '.0' + pr + - ' <' + M + '.' + (+m + 1) + '.0' + pr - } - - debug('xRange return', ret) - - return ret - }) -} - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars (comp, options) { - debug('replaceStars', comp, options) - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[t.STAR], '') -} - -// This function is passed to string.replace(re[t.HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace ($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - if (isX(fM)) { - from = '' - } else if (isX(fm)) { - from = '>=' + fM + '.0.0' - } else if (isX(fp)) { - from = '>=' + fM + '.' + fm + '.0' - } else { - from = '>=' + from - } - - if (isX(tM)) { - to = '' - } else if (isX(tm)) { - to = '<' + (+tM + 1) + '.0.0' - } else if (isX(tp)) { - to = '<' + tM + '.' + (+tm + 1) + '.0' - } else if (tpr) { - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr - } else { - to = '<=' + to - } - - return (from + ' ' + to).trim() -} - -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function (version) { - if (!version) { - return false - } - - if (typeof version === 'string') { - try { - version = new SemVer(version, this.options) - } catch (er) { - return false - } - } - - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version, this.options)) { - return true - } - } - return false -} - -function testSet (set, version, options) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) { - return false - } - } - - if (version.prerelease.length && !options.includePrerelease) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (i = 0; i < set.length; i++) { - debug(set[i].semver) - if (set[i].semver === ANY) { - continue - } - - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) { - return true - } - } - } - - // Version has a -pre, but it's not one of the ones we like. - return false - } - - return true -} - -exports.satisfies = satisfies -function satisfies (version, range, options) { - try { - range = new Range(range, options) - } catch (er) { - return false - } - return range.test(version) -} - -exports.maxSatisfying = maxSatisfying -function maxSatisfying (versions, range, options) { - var max = null - var maxSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!max || maxSV.compare(v) === -1) { - // compare(max, v, true) - max = v - maxSV = new SemVer(max, options) - } - } - }) - return max -} - -exports.minSatisfying = minSatisfying -function minSatisfying (versions, range, options) { - var min = null - var minSV = null - try { - var rangeObj = new Range(range, options) - } catch (er) { - return null - } - versions.forEach(function (v) { - if (rangeObj.test(v)) { - // satisfies(v, range, options) - if (!min || minSV.compare(v) === 1) { - // compare(min, v, true) - min = v - minSV = new SemVer(min, options) - } - } - }) - return min -} - -exports.minVersion = minVersion -function minVersion (range, loose) { - range = new Range(range, loose) - - var minver = new SemVer('0.0.0') - if (range.test(minver)) { - return minver - } - - minver = new SemVer('0.0.0-0') - if (range.test(minver)) { - return minver - } - - minver = null - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] - - comparators.forEach(function (comparator) { - // Clone to avoid manipulating the comparator's semver object. - var compver = new SemVer(comparator.semver.version) - switch (comparator.operator) { - case '>': - if (compver.prerelease.length === 0) { - compver.patch++ - } else { - compver.prerelease.push(0) - } - compver.raw = compver.format() - /* fallthrough */ - case '': - case '>=': - if (!minver || gt(minver, compver)) { - minver = compver - } - break - case '<': - case '<=': - /* Ignore maximum versions */ - break - /* istanbul ignore next */ - default: - throw new Error('Unexpected operation: ' + comparator.operator) - } - }) - } - - if (minver && range.test(minver)) { - return minver - } - - return null -} - -exports.validRange = validRange -function validRange (range, options) { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, options).range || '*' - } catch (er) { - return null - } -} - -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr -function ltr (version, range, options) { - return outside(version, range, '<', options) -} - -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr -function gtr (version, range, options) { - return outside(version, range, '>', options) -} - -exports.outside = outside -function outside (version, range, hilo, options) { - version = new SemVer(version, options) - range = new Range(range, options) - - var gtfn, ltefn, ltfn, comp, ecomp - switch (hilo) { - case '>': - gtfn = gt - ltefn = lte - ltfn = lt - comp = '>' - ecomp = '>=' - break - case '<': - gtfn = lt - ltefn = gte - ltfn = gt - comp = '<' - ecomp = '<=' - break - default: - throw new TypeError('Must provide a hilo val of "<" or ">"') - } - - // If it satisifes the range it is not outside - if (satisfies(version, range, options)) { - return false - } - - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. - - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i] - - var high = null - var low = null - - comparators.forEach(function (comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator - low = low || comparator - if (gtfn(comparator.semver, high.semver, options)) { - high = comparator - } else if (ltfn(comparator.semver, low.semver, options)) { - low = comparator - } - }) - - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false - } - - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false - } - } - return true -} - -exports.prerelease = prerelease -function prerelease (version, options) { - var parsed = parse(version, options) - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null -} - -exports.intersects = intersects -function intersects (r1, r2, options) { - r1 = new Range(r1, options) - r2 = new Range(r2, options) - return r1.intersects(r2) -} - -exports.coerce = coerce -function coerce (version, options) { - if (version instanceof SemVer) { - return version - } - - if (typeof version === 'number') { - version = String(version) - } - - if (typeof version !== 'string') { - return null - } - - options = options || {} - - var match = null - if (!options.rtl) { - match = version.match(re[t.COERCE]) - } else { - // Find the right-most coercible string that does not share - // a terminus with a more left-ward coercible string. - // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' - // - // Walk through the string checking with a /g regexp - // Manually set the index so as to pick up overlapping matches. - // Stop when we get a match that ends at the string end, since no - // coercible string can be more right-ward without the same terminus. - var next - while ((next = re[t.COERCERTL].exec(version)) && - (!match || match.index + match[0].length !== version.length) - ) { - if (!match || - next.index + next[0].length !== match.index + match[0].length) { - match = next - } - re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length - } - // leave it in a clean state - re[t.COERCERTL].lastIndex = -1 - } - - if (match === null) { - return null - } - - return parse(match[2] + - '.' + (match[3] || '0') + - '.' + (match[4] || '0'), options) -} - - -/***/ }), - -/***/ 357: -/***/ (function(module) { - -module.exports = require("assert"); - -/***/ }), - -/***/ 413: -/***/ (function(module, __unusedexports, __webpack_require__) { - -module.exports = __webpack_require__(141); - - -/***/ }), - -/***/ 417: -/***/ (function(module) { - -module.exports = require("crypto"); - -/***/ }), - -/***/ 431: -/***/ (function(__unusedmodule, exports, __webpack_require__) { - -"use strict"; - -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const os = __importStar(__webpack_require__(87)); -/** - * Commands - * - * Command Format: - * ::name key=value,key=value::message - * - * Examples: - * ::warning::This is the message - * ::set-env name=MY_VAR::some value - */ -function issueCommand(command, properties, message) { - const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os.EOL); -} -exports.issueCommand = issueCommand; -function issue(name, message = '') { - issueCommand(name, {}, message); -} -exports.issue = issue; -const CMD_STRING = '::'; -class Command { - constructor(command, properties, message) { - if (!command) { - command = 'missing.command'; - } - this.command = command; - this.properties = properties; - this.message = message; - } - toString() { - let cmdStr = CMD_STRING + this.command; - if (this.properties && Object.keys(this.properties).length > 0) { - cmdStr += ' '; - let first = true; - for (const key in this.properties) { - if (this.properties.hasOwnProperty(key)) { - const val = this.properties[key]; - if (val) { - if (first) { - first = false; - } - else { - cmdStr += ','; - } - cmdStr += `${key}=${escapeProperty(val)}`; - } - } - } - } - cmdStr += `${CMD_STRING}${escapeData(this.message)}`; - return cmdStr; - } -} -/** - * Sanitizes an input into a string so it can be passed into issueCommand safely - * @param input input to sanitize into a string - */ -function toCommandValue(input) { - if (input === null || input === undefined) { - return ''; - } - else if (typeof input === 'string' || input instanceof String) { - return input; - } - return JSON.stringify(input); -} -exports.toCommandValue = toCommandValue; -function escapeData(s) { - return toCommandValue(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A'); -} -function escapeProperty(s) { - return toCommandValue(s) - .replace(/%/g, '%25') - .replace(/\r/g, '%0D') - .replace(/\n/g, '%0A') - .replace(/:/g, '%3A') - .replace(/,/g, '%2C'); -} -//# sourceMappingURL=command.js.map - -/***/ }), - -/***/ 453: -/***/ (function(__unusedmodule, exports, __webpack_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.getAndUnsetConfigOption = exports.getConfigOption = exports.configOptionExists = exports.unsetConfigOption = exports.addConfigOption = exports.execGit = exports.getRepoPath = exports.ConfigOption = void 0; -const core = __importStar(__webpack_require__(470)); -const exec = __importStar(__webpack_require__(986)); -const path = __importStar(__webpack_require__(622)); -class GitOutput { - constructor() { - this.stdout = ''; - this.exitCode = 0; - } -} -class ConfigOption { - constructor() { - this.name = ''; - this.value = ''; - } -} -exports.ConfigOption = ConfigOption; -function getRepoPath(relativePath) { - let githubWorkspacePath = process.env['GITHUB_WORKSPACE']; - if (!githubWorkspacePath) { - throw new Error('GITHUB_WORKSPACE not defined'); - } - githubWorkspacePath = path.resolve(githubWorkspacePath); - core.debug(`githubWorkspacePath: ${githubWorkspacePath}`); - let repoPath = githubWorkspacePath; - if (relativePath) - repoPath = path.resolve(repoPath, relativePath); - core.debug(`repoPath: ${repoPath}`); - return repoPath; -} -exports.getRepoPath = getRepoPath; -function execGit(repoPath, args, ignoreReturnCode = false) { - return __awaiter(this, void 0, void 0, function* () { - const result = new GitOutput(); - const stdout = []; - const options = { - cwd: repoPath, - ignoreReturnCode: ignoreReturnCode, - listeners: { - stdout: (data) => { - stdout.push(data.toString()); - } - } + parseRepository(repository) { + const [owner, repo] = repository.split('/'); + return { + owner: owner, + repo: repo }; - result.exitCode = yield exec.exec('git', args, options); - result.stdout = stdout.join(''); - return result; - }); -} -exports.execGit = execGit; -function addConfigOption(repoPath, name, value) { - return __awaiter(this, void 0, void 0, function* () { - const result = yield execGit(repoPath, ['config', '--local', '--add', name, value], true); - return result.exitCode === 0; - }); -} -exports.addConfigOption = addConfigOption; -function unsetConfigOption(repoPath, name, valueRegex = '.') { - return __awaiter(this, void 0, void 0, function* () { - const result = yield execGit(repoPath, ['config', '--local', '--unset', name, valueRegex], true); - return result.exitCode === 0; - }); -} -exports.unsetConfigOption = unsetConfigOption; -function configOptionExists(repoPath, name, valueRegex = '.') { - return __awaiter(this, void 0, void 0, function* () { - const result = yield execGit(repoPath, ['config', '--local', '--name-only', '--get-regexp', name, valueRegex], true); - return result.exitCode === 0; - }); -} -exports.configOptionExists = configOptionExists; -function getConfigOption(repoPath, name, valueRegex = '.') { - return __awaiter(this, void 0, void 0, function* () { - const option = new ConfigOption(); - const result = yield execGit(repoPath, ['config', '--local', '--get-regexp', name, valueRegex], true); - option.name = name; - option.value = result.stdout.trim().split(`${name} `)[1]; - return option; - }); -} -exports.getConfigOption = getConfigOption; -function getAndUnsetConfigOption(repoPath, name, valueRegex = '.') { - return __awaiter(this, void 0, void 0, function* () { - if (yield configOptionExists(repoPath, name, valueRegex)) { - const option = yield getConfigOption(repoPath, name, valueRegex); - if (yield unsetConfigOption(repoPath, name, valueRegex)) { - core.debug(`Unset config option '${name}'`); - return option; + } + createOrUpdate(inputs, baseRepository, headBranch) { + return __awaiter(this, void 0, void 0, function* () { + // Try to create the pull request + try { + const { data: pull } = yield this.octokit.pulls.create(Object.assign(Object.assign({}, this.parseRepository(baseRepository)), { title: inputs.title, head: headBranch, base: inputs.base, body: inputs.body, draft: inputs.draft })); + core.info(`Created pull request #${pull.number} (${headBranch} => ${inputs.base})`); + return pull.number; } - } - return new ConfigOption(); - }); -} -exports.getAndUnsetConfigOption = getAndUnsetConfigOption; - - -/***/ }), - -/***/ 470: -/***/ (function(__unusedmodule, exports, __webpack_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const command_1 = __webpack_require__(431); -const os = __importStar(__webpack_require__(87)); -const path = __importStar(__webpack_require__(622)); -/** - * The code to exit an action - */ -var ExitCode; -(function (ExitCode) { - /** - * A code indicating that the action was successful - */ - ExitCode[ExitCode["Success"] = 0] = "Success"; - /** - * A code indicating that the action was a failure - */ - ExitCode[ExitCode["Failure"] = 1] = "Failure"; -})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); -//----------------------------------------------------------------------- -// Variables -//----------------------------------------------------------------------- -/** - * Sets env variable for this action and future actions in the job - * @param name the name of the variable to set - * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function exportVariable(name, val) { - const convertedVal = command_1.toCommandValue(val); - process.env[name] = convertedVal; - command_1.issueCommand('set-env', { name }, convertedVal); -} -exports.exportVariable = exportVariable; -/** - * Registers a secret which will get masked from logs - * @param secret value of the secret - */ -function setSecret(secret) { - command_1.issueCommand('add-mask', {}, secret); -} -exports.setSecret = setSecret; -/** - * Prepends inputPath to the PATH (for this action and future actions) - * @param inputPath - */ -function addPath(inputPath) { - command_1.issueCommand('add-path', {}, inputPath); - process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; -} -exports.addPath = addPath; -/** - * Gets the value of an input. The value is also trimmed. - * - * @param name name of the input to get - * @param options optional. See InputOptions. - * @returns string - */ -function getInput(name, options) { - const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; - if (options && options.required && !val) { - throw new Error(`Input required and not supplied: ${name}`); - } - return val.trim(); -} -exports.getInput = getInput; -/** - * Sets the value of an output. - * - * @param name name of the output to set - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function setOutput(name, value) { - command_1.issueCommand('set-output', { name }, value); -} -exports.setOutput = setOutput; -/** - * Enables or disables the echoing of commands into stdout for the rest of the step. - * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. - * - */ -function setCommandEcho(enabled) { - command_1.issue('echo', enabled ? 'on' : 'off'); -} -exports.setCommandEcho = setCommandEcho; -//----------------------------------------------------------------------- -// Results -//----------------------------------------------------------------------- -/** - * Sets the action status to failed. - * When the action exits it will be with an exit code of 1 - * @param message add error issue message - */ -function setFailed(message) { - process.exitCode = ExitCode.Failure; - error(message); -} -exports.setFailed = setFailed; -//----------------------------------------------------------------------- -// Logging Commands -//----------------------------------------------------------------------- -/** - * Gets whether Actions Step Debug is on or not - */ -function isDebug() { - return process.env['RUNNER_DEBUG'] === '1'; -} -exports.isDebug = isDebug; -/** - * Writes debug message to user log - * @param message debug message - */ -function debug(message) { - command_1.issueCommand('debug', {}, message); -} -exports.debug = debug; -/** - * Adds an error issue - * @param message error issue message. Errors will be converted to string via toString() - */ -function error(message) { - command_1.issue('error', message instanceof Error ? message.toString() : message); -} -exports.error = error; -/** - * Adds an warning issue - * @param message warning issue message. Errors will be converted to string via toString() - */ -function warning(message) { - command_1.issue('warning', message instanceof Error ? message.toString() : message); -} -exports.warning = warning; -/** - * Writes info to log with console.log. - * @param message info message - */ -function info(message) { - process.stdout.write(message + os.EOL); -} -exports.info = info; -/** - * Begin an output group. - * - * Output until the next `groupEnd` will be foldable in this group - * - * @param name The name of the output group - */ -function startGroup(name) { - command_1.issue('group', name); -} -exports.startGroup = startGroup; -/** - * End an output group. - */ -function endGroup() { - command_1.issue('endgroup'); -} -exports.endGroup = endGroup; -/** - * Wrap an asynchronous function call in a group. - * - * Returns the same type as the function itself. - * - * @param name The name of the group - * @param fn The function to wrap in the group - */ -function group(name, fn) { - return __awaiter(this, void 0, void 0, function* () { - startGroup(name); - let result; - try { - result = yield fn(); - } - finally { - endGroup(); - } - return result; - }); -} -exports.group = group; -//----------------------------------------------------------------------- -// Wrapper action state -//----------------------------------------------------------------------- -/** - * Saves state for current action, the state can only be retrieved by this action's post job execution. - * - * @param name name of the state to store - * @param value value to store. Non-string values will be converted to a string via JSON.stringify - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function saveState(name, value) { - command_1.issueCommand('save-state', { name }, value); -} -exports.saveState = saveState; -/** - * Gets the value of an state set by this action's main execution. - * - * @param name name of the state to get - * @returns string - */ -function getState(name) { - return process.env[`STATE_${name}`] || ''; -} -exports.getState = getState; -//# sourceMappingURL=core.js.map - -/***/ }), - -/***/ 533: -/***/ (function(__unusedmodule, exports, __webpack_require__) { - -"use strict"; - -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const core = __importStar(__webpack_require__(470)); -const io = __importStar(__webpack_require__(1)); -const fs = __importStar(__webpack_require__(747)); -const os = __importStar(__webpack_require__(87)); -const path = __importStar(__webpack_require__(622)); -const httpm = __importStar(__webpack_require__(539)); -const semver = __importStar(__webpack_require__(280)); -const stream = __importStar(__webpack_require__(794)); -const util = __importStar(__webpack_require__(669)); -const v4_1 = __importDefault(__webpack_require__(826)); -const exec_1 = __webpack_require__(986); -const assert_1 = __webpack_require__(357); -const retry_helper_1 = __webpack_require__(979); -class HTTPError extends Error { - constructor(httpStatusCode) { - super(`Unexpected HTTP response: ${httpStatusCode}`); - this.httpStatusCode = httpStatusCode; - Object.setPrototypeOf(this, new.target.prototype); - } -} -exports.HTTPError = HTTPError; -const IS_WINDOWS = process.platform === 'win32'; -const userAgent = 'actions/tool-cache'; -/** - * Download a tool from an url and stream it into a file - * - * @param url url of tool to download - * @param dest path to download tool - * @returns path to downloaded tool - */ -function downloadTool(url, dest) { - return __awaiter(this, void 0, void 0, function* () { - dest = dest || path.join(_getTempDirectory(), v4_1.default()); - yield io.mkdirP(path.dirname(dest)); - core.debug(`Downloading ${url}`); - core.debug(`Destination ${dest}`); - const maxAttempts = 3; - const minSeconds = _getGlobal('TEST_DOWNLOAD_TOOL_RETRY_MIN_SECONDS', 10); - const maxSeconds = _getGlobal('TEST_DOWNLOAD_TOOL_RETRY_MAX_SECONDS', 20); - const retryHelper = new retry_helper_1.RetryHelper(maxAttempts, minSeconds, maxSeconds); - return yield retryHelper.execute(() => __awaiter(this, void 0, void 0, function* () { - return yield downloadToolAttempt(url, dest || ''); - }), (err) => { - if (err instanceof HTTPError && err.httpStatusCode) { - // Don't retry anything less than 500, except 408 Request Timeout and 429 Too Many Requests - if (err.httpStatusCode < 500 && - err.httpStatusCode !== 408 && - err.httpStatusCode !== 429) { - return false; + catch (e) { + if (!e.message || + !e.message.includes(`A pull request already exists for ${headBranch}`)) { + throw e; } } - // Otherwise retry - return true; + // Update the pull request that exists for this branch and base + const { data: pulls } = yield this.octokit.pulls.list(Object.assign(Object.assign({}, this.parseRepository(baseRepository)), { state: 'open', head: headBranch, base: inputs.base })); + const { data: pull } = yield this.octokit.pulls.update(Object.assign(Object.assign({}, this.parseRepository(baseRepository)), { pull_number: pulls[0].number, title: inputs.title, body: inputs.body, draft: inputs.draft })); + core.info(`Updated pull request #${pull.number} (${headBranch} => ${inputs.base})`); + return pull.number; }); - }); -} -exports.downloadTool = downloadTool; -function downloadToolAttempt(url, dest) { - return __awaiter(this, void 0, void 0, function* () { - if (fs.existsSync(dest)) { - throw new Error(`Destination file path ${dest} already exists`); - } - // Get the response headers - const http = new httpm.HttpClient(userAgent, [], { - allowRetries: false - }); - const response = yield http.get(url); - if (response.message.statusCode !== 200) { - const err = new HTTPError(response.message.statusCode); - core.debug(`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`); - throw err; - } - // Download the response body - const pipeline = util.promisify(stream.pipeline); - const responseMessageFactory = _getGlobal('TEST_DOWNLOAD_TOOL_RESPONSE_MESSAGE_FACTORY', () => response.message); - const readStream = responseMessageFactory(); - let succeeded = false; - try { - yield pipeline(readStream, fs.createWriteStream(dest)); - core.debug('download complete'); - succeeded = true; - return dest; - } - finally { - // Error, delete dest before retry - if (!succeeded) { - core.debug('download failed'); + } + createOrUpdatePullRequest(inputs, headRepository) { + return __awaiter(this, void 0, void 0, function* () { + const { data: headRepo } = yield this.octokit.repos.get(Object.assign({}, this.parseRepository(headRepository))); + if (inputs.requestToParent && !headRepo.parent) { + throw new Error(`The checked out repository is not a fork. Input 'request-to-parent' should be set to 'false'.`); + } + const baseRepository = inputs.requestToParent + ? headRepo.parent.full_name + : headRepository; + const headBranch = `${headRepo.owner.login}:${inputs.branch}`; + // Create or update the pull request + const pullNumber = yield this.createOrUpdate(inputs, baseRepository, headBranch); + // Set output + core.setOutput('pull-request-number', pullNumber); + // Set milestone, labels and assignees + const updateIssueParams = {}; + if (inputs.milestone) { + updateIssueParams['milestone'] = inputs.milestone; + core.info(`Applying milestone '${inputs.milestone}'`); + } + if (inputs.labels.length > 0) { + updateIssueParams['labels'] = inputs.labels; + core.info(`Applying labels '${inputs.labels}'`); + } + if (inputs.assignees.length > 0) { + updateIssueParams['assignees'] = inputs.assignees; + core.info(`Applying assignees '${inputs.assignees}'`); + } + if (Object.keys(updateIssueParams).length > 0) { + yield this.octokit.issues.update(Object.assign(Object.assign(Object.assign({}, this.parseRepository(baseRepository)), { issue_number: pullNumber }), updateIssueParams)); + } + // Request reviewers and team reviewers + const requestReviewersParams = {}; + if (inputs.reviewers.length > 0) { + requestReviewersParams['reviewers'] = inputs.reviewers; + core.info(`Requesting reviewers '${inputs.reviewers}'`); + } + if (inputs.teamReviewers.length > 0) { + requestReviewersParams['team_reviewers'] = inputs.teamReviewers; + core.info(`Requesting team reviewers '${inputs.teamReviewers}'`); + } + if (Object.keys(requestReviewersParams).length > 0) { try { - yield io.rmRF(dest); + yield this.octokit.pulls.requestReviewers(Object.assign(Object.assign(Object.assign({}, this.parseRepository(baseRepository)), { pull_number: pullNumber }), requestReviewersParams)); } - catch (err) { - core.debug(`Failed to delete '${dest}'. ${err.message}`); - } - } - } - }); -} -/** - * Extract a .7z file - * - * @param file path to the .7z file - * @param dest destination directory. Optional. - * @param _7zPath path to 7zr.exe. Optional, for long path support. Most .7z archives do not have this - * problem. If your .7z archive contains very long paths, you can pass the path to 7zr.exe which will - * gracefully handle long paths. By default 7zdec.exe is used because it is a very small program and is - * bundled with the tool lib. However it does not support long paths. 7zr.exe is the reduced command line - * interface, it is smaller than the full command line interface, and it does support long paths. At the - * time of this writing, it is freely available from the LZMA SDK that is available on the 7zip website. - * Be sure to check the current license agreement. If 7zr.exe is bundled with your action, then the path - * to 7zr.exe can be pass to this function. - * @returns path to the destination directory - */ -function extract7z(file, dest, _7zPath) { - return __awaiter(this, void 0, void 0, function* () { - assert_1.ok(IS_WINDOWS, 'extract7z() not supported on current OS'); - assert_1.ok(file, 'parameter "file" is required'); - dest = yield _createExtractFolder(dest); - const originalCwd = process.cwd(); - process.chdir(dest); - if (_7zPath) { - try { - const args = [ - 'x', - '-bb1', - '-bd', - '-sccUTF-8', - file - ]; - const options = { - silent: true - }; - yield exec_1.exec(`"${_7zPath}"`, args, options); - } - finally { - process.chdir(originalCwd); - } - } - else { - const escapedScript = path - .join(__dirname, '..', 'scripts', 'Invoke-7zdec.ps1') - .replace(/'/g, "''") - .replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines - const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); - const escapedTarget = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ''); - const command = `& '${escapedScript}' -Source '${escapedFile}' -Target '${escapedTarget}'`; - const args = [ - '-NoLogo', - '-Sta', - '-NoProfile', - '-NonInteractive', - '-ExecutionPolicy', - 'Unrestricted', - '-Command', - command - ]; - const options = { - silent: true - }; - try { - const powershellPath = yield io.which('powershell', true); - yield exec_1.exec(`"${powershellPath}"`, args, options); - } - finally { - process.chdir(originalCwd); - } - } - return dest; - }); -} -exports.extract7z = extract7z; -/** - * Extract a compressed tar archive - * - * @param file path to the tar - * @param dest destination directory. Optional. - * @param flags flags for the tar command to use for extraction. Defaults to 'xz' (extracting gzipped tars). Optional. - * @returns path to the destination directory - */ -function extractTar(file, dest, flags = 'xz') { - return __awaiter(this, void 0, void 0, function* () { - if (!file) { - throw new Error("parameter 'file' is required"); - } - // Create dest - dest = yield _createExtractFolder(dest); - // Determine whether GNU tar - core.debug('Checking tar --version'); - let versionOutput = ''; - yield exec_1.exec('tar --version', [], { - ignoreReturnCode: true, - silent: true, - listeners: { - stdout: (data) => (versionOutput += data.toString()), - stderr: (data) => (versionOutput += data.toString()) - } - }); - core.debug(versionOutput.trim()); - const isGnuTar = versionOutput.toUpperCase().includes('GNU TAR'); - // Initialize args - const args = [flags]; - let destArg = dest; - let fileArg = file; - if (IS_WINDOWS && isGnuTar) { - args.push('--force-local'); - destArg = dest.replace(/\\/g, '/'); - // Technically only the dest needs to have `/` but for aesthetic consistency - // convert slashes in the file arg too. - fileArg = file.replace(/\\/g, '/'); - } - if (isGnuTar) { - // Suppress warnings when using GNU tar to extract archives created by BSD tar - args.push('--warning=no-unknown-keyword'); - } - args.push('-C', destArg, '-f', fileArg); - yield exec_1.exec(`tar`, args); - return dest; - }); -} -exports.extractTar = extractTar; -/** - * Extract a zip - * - * @param file path to the zip - * @param dest destination directory. Optional. - * @returns path to the destination directory - */ -function extractZip(file, dest) { - return __awaiter(this, void 0, void 0, function* () { - if (!file) { - throw new Error("parameter 'file' is required"); - } - dest = yield _createExtractFolder(dest); - if (IS_WINDOWS) { - yield extractZipWin(file, dest); - } - else { - yield extractZipNix(file, dest); - } - return dest; - }); -} -exports.extractZip = extractZip; -function extractZipWin(file, dest) { - return __awaiter(this, void 0, void 0, function* () { - // build the powershell command - const escapedFile = file.replace(/'/g, "''").replace(/"|\n|\r/g, ''); // double-up single quotes, remove double quotes and newlines - const escapedDest = dest.replace(/'/g, "''").replace(/"|\n|\r/g, ''); - const command = `$ErrorActionPreference = 'Stop' ; try { Add-Type -AssemblyName System.IO.Compression.FileSystem } catch { } ; [System.IO.Compression.ZipFile]::ExtractToDirectory('${escapedFile}', '${escapedDest}')`; - // run powershell - const powershellPath = yield io.which('powershell'); - const args = [ - '-NoLogo', - '-Sta', - '-NoProfile', - '-NonInteractive', - '-ExecutionPolicy', - 'Unrestricted', - '-Command', - command - ]; - yield exec_1.exec(`"${powershellPath}"`, args); - }); -} -function extractZipNix(file, dest) { - return __awaiter(this, void 0, void 0, function* () { - const unzipPath = yield io.which('unzip'); - yield exec_1.exec(`"${unzipPath}"`, [file], { cwd: dest }); - }); -} -/** - * Caches a directory and installs it into the tool cacheDir - * - * @param sourceDir the directory to cache into tools - * @param tool tool name - * @param version version of the tool. semver format - * @param arch architecture of the tool. Optional. Defaults to machine architecture - */ -function cacheDir(sourceDir, tool, version, arch) { - return __awaiter(this, void 0, void 0, function* () { - version = semver.clean(version) || version; - arch = arch || os.arch(); - core.debug(`Caching tool ${tool} ${version} ${arch}`); - core.debug(`source dir: ${sourceDir}`); - if (!fs.statSync(sourceDir).isDirectory()) { - throw new Error('sourceDir is not a directory'); - } - // Create the tool dir - const destPath = yield _createToolPath(tool, version, arch); - // copy each child item. do not move. move can fail on Windows - // due to anti-virus software having an open handle on a file. - for (const itemName of fs.readdirSync(sourceDir)) { - const s = path.join(sourceDir, itemName); - yield io.cp(s, destPath, { recursive: true }); - } - // write .complete - _completeToolPath(tool, version, arch); - return destPath; - }); -} -exports.cacheDir = cacheDir; -/** - * Caches a downloaded file (GUID) and installs it - * into the tool cache with a given targetName - * - * @param sourceFile the file to cache into tools. Typically a result of downloadTool which is a guid. - * @param targetFile the name of the file name in the tools directory - * @param tool tool name - * @param version version of the tool. semver format - * @param arch architecture of the tool. Optional. Defaults to machine architecture - */ -function cacheFile(sourceFile, targetFile, tool, version, arch) { - return __awaiter(this, void 0, void 0, function* () { - version = semver.clean(version) || version; - arch = arch || os.arch(); - core.debug(`Caching tool ${tool} ${version} ${arch}`); - core.debug(`source file: ${sourceFile}`); - if (!fs.statSync(sourceFile).isFile()) { - throw new Error('sourceFile is not a file'); - } - // create the tool dir - const destFolder = yield _createToolPath(tool, version, arch); - // copy instead of move. move can fail on Windows due to - // anti-virus software having an open handle on a file. - const destPath = path.join(destFolder, targetFile); - core.debug(`destination file ${destPath}`); - yield io.cp(sourceFile, destPath); - // write .complete - _completeToolPath(tool, version, arch); - return destFolder; - }); -} -exports.cacheFile = cacheFile; -/** - * Finds the path to a tool version in the local installed tool cache - * - * @param toolName name of the tool - * @param versionSpec version of the tool - * @param arch optional arch. defaults to arch of computer - */ -function find(toolName, versionSpec, arch) { - if (!toolName) { - throw new Error('toolName parameter is required'); - } - if (!versionSpec) { - throw new Error('versionSpec parameter is required'); - } - arch = arch || os.arch(); - // attempt to resolve an explicit version - if (!_isExplicitVersion(versionSpec)) { - const localVersions = findAllVersions(toolName, arch); - const match = _evaluateVersions(localVersions, versionSpec); - versionSpec = match; - } - // check for the explicit version in the cache - let toolPath = ''; - if (versionSpec) { - versionSpec = semver.clean(versionSpec) || ''; - const cachePath = path.join(_getCacheDirectory(), toolName, versionSpec, arch); - core.debug(`checking cache: ${cachePath}`); - if (fs.existsSync(cachePath) && fs.existsSync(`${cachePath}.complete`)) { - core.debug(`Found tool in cache ${toolName} ${versionSpec} ${arch}`); - toolPath = cachePath; - } - else { - core.debug('not found'); - } - } - return toolPath; -} -exports.find = find; -/** - * Finds the paths to all versions of a tool that are installed in the local tool cache - * - * @param toolName name of the tool - * @param arch optional arch. defaults to arch of computer - */ -function findAllVersions(toolName, arch) { - const versions = []; - arch = arch || os.arch(); - const toolPath = path.join(_getCacheDirectory(), toolName); - if (fs.existsSync(toolPath)) { - const children = fs.readdirSync(toolPath); - for (const child of children) { - if (_isExplicitVersion(child)) { - const fullPath = path.join(toolPath, child, arch || ''); - if (fs.existsSync(fullPath) && fs.existsSync(`${fullPath}.complete`)) { - versions.push(child); - } - } - } - } - return versions; -} -exports.findAllVersions = findAllVersions; -function _createExtractFolder(dest) { - return __awaiter(this, void 0, void 0, function* () { - if (!dest) { - // create a temp dir - dest = path.join(_getTempDirectory(), v4_1.default()); - } - yield io.mkdirP(dest); - return dest; - }); -} -function _createToolPath(tool, version, arch) { - return __awaiter(this, void 0, void 0, function* () { - const folderPath = path.join(_getCacheDirectory(), tool, semver.clean(version) || version, arch || ''); - core.debug(`destination ${folderPath}`); - const markerPath = `${folderPath}.complete`; - yield io.rmRF(folderPath); - yield io.rmRF(markerPath); - yield io.mkdirP(folderPath); - return folderPath; - }); -} -function _completeToolPath(tool, version, arch) { - const folderPath = path.join(_getCacheDirectory(), tool, semver.clean(version) || version, arch || ''); - const markerPath = `${folderPath}.complete`; - fs.writeFileSync(markerPath, ''); - core.debug('finished caching tool'); -} -function _isExplicitVersion(versionSpec) { - const c = semver.clean(versionSpec) || ''; - core.debug(`isExplicit: ${c}`); - const valid = semver.valid(c) != null; - core.debug(`explicit? ${valid}`); - return valid; -} -function _evaluateVersions(versions, versionSpec) { - let version = ''; - core.debug(`evaluating ${versions.length} versions`); - versions = versions.sort((a, b) => { - if (semver.gt(a, b)) { - return 1; - } - return -1; - }); - for (let i = versions.length - 1; i >= 0; i--) { - const potential = versions[i]; - const satisfied = semver.satisfies(potential, versionSpec); - if (satisfied) { - version = potential; - break; - } - } - if (version) { - core.debug(`matched: ${version}`); - } - else { - core.debug('match not found'); - } - return version; -} -/** - * Gets RUNNER_TOOL_CACHE - */ -function _getCacheDirectory() { - const cacheDirectory = process.env['RUNNER_TOOL_CACHE'] || ''; - assert_1.ok(cacheDirectory, 'Expected RUNNER_TOOL_CACHE to be defined'); - return cacheDirectory; -} -/** - * Gets RUNNER_TEMP - */ -function _getTempDirectory() { - const tempDirectory = process.env['RUNNER_TEMP'] || ''; - assert_1.ok(tempDirectory, 'Expected RUNNER_TEMP to be defined'); - return tempDirectory; -} -/** - * Gets a global variable - */ -function _getGlobal(key, defaultValue) { - /* eslint-disable @typescript-eslint/no-explicit-any */ - const value = global[key]; - /* eslint-enable @typescript-eslint/no-explicit-any */ - return value !== undefined ? value : defaultValue; -} -//# sourceMappingURL=tool-cache.js.map - -/***/ }), - -/***/ 539: -/***/ (function(__unusedmodule, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const url = __webpack_require__(835); -const http = __webpack_require__(605); -const https = __webpack_require__(211); -const pm = __webpack_require__(950); -let tunnel; -var HttpCodes; -(function (HttpCodes) { - HttpCodes[HttpCodes["OK"] = 200] = "OK"; - HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; - HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; - HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; - HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; - HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; - HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; - HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; - HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; - HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; - HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; - HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; - HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; - HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; - HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; - HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; - HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; - HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; - HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; - HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; - HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; - HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; - HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; - HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; - HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; - HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; - HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; -})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); -var Headers; -(function (Headers) { - Headers["Accept"] = "accept"; - Headers["ContentType"] = "content-type"; -})(Headers = exports.Headers || (exports.Headers = {})); -var MediaTypes; -(function (MediaTypes) { - MediaTypes["ApplicationJson"] = "application/json"; -})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {})); -/** - * Returns the proxy URL, depending upon the supplied url and proxy environment variables. - * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com - */ -function getProxyUrl(serverUrl) { - let proxyUrl = pm.getProxyUrl(url.parse(serverUrl)); - return proxyUrl ? proxyUrl.href : ''; -} -exports.getProxyUrl = getProxyUrl; -const HttpRedirectCodes = [ - HttpCodes.MovedPermanently, - HttpCodes.ResourceMoved, - HttpCodes.SeeOther, - HttpCodes.TemporaryRedirect, - HttpCodes.PermanentRedirect -]; -const HttpResponseRetryCodes = [ - HttpCodes.BadGateway, - HttpCodes.ServiceUnavailable, - HttpCodes.GatewayTimeout -]; -const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; -const ExponentialBackoffCeiling = 10; -const ExponentialBackoffTimeSlice = 5; -class HttpClientResponse { - constructor(message) { - this.message = message; - } - readBody() { - return new Promise(async (resolve, reject) => { - let output = Buffer.alloc(0); - this.message.on('data', (chunk) => { - output = Buffer.concat([output, chunk]); - }); - this.message.on('end', () => { - resolve(output.toString()); - }); - }); - } -} -exports.HttpClientResponse = HttpClientResponse; -function isHttps(requestUrl) { - let parsedUrl = url.parse(requestUrl); - return parsedUrl.protocol === 'https:'; -} -exports.isHttps = isHttps; -class HttpClient { - constructor(userAgent, handlers, requestOptions) { - this._ignoreSslError = false; - this._allowRedirects = true; - this._allowRedirectDowngrade = false; - this._maxRedirects = 50; - this._allowRetries = false; - this._maxRetries = 1; - this._keepAlive = false; - this._disposed = false; - this.userAgent = userAgent; - this.handlers = handlers || []; - this.requestOptions = requestOptions; - if (requestOptions) { - if (requestOptions.ignoreSslError != null) { - this._ignoreSslError = requestOptions.ignoreSslError; - } - this._socketTimeout = requestOptions.socketTimeout; - if (requestOptions.allowRedirects != null) { - this._allowRedirects = requestOptions.allowRedirects; - } - if (requestOptions.allowRedirectDowngrade != null) { - this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; - } - if (requestOptions.maxRedirects != null) { - this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); - } - if (requestOptions.keepAlive != null) { - this._keepAlive = requestOptions.keepAlive; - } - if (requestOptions.allowRetries != null) { - this._allowRetries = requestOptions.allowRetries; - } - if (requestOptions.maxRetries != null) { - this._maxRetries = requestOptions.maxRetries; - } - } - } - options(requestUrl, additionalHeaders) { - return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); - } - get(requestUrl, additionalHeaders) { - return this.request('GET', requestUrl, null, additionalHeaders || {}); - } - del(requestUrl, additionalHeaders) { - return this.request('DELETE', requestUrl, null, additionalHeaders || {}); - } - post(requestUrl, data, additionalHeaders) { - return this.request('POST', requestUrl, data, additionalHeaders || {}); - } - patch(requestUrl, data, additionalHeaders) { - return this.request('PATCH', requestUrl, data, additionalHeaders || {}); - } - put(requestUrl, data, additionalHeaders) { - return this.request('PUT', requestUrl, data, additionalHeaders || {}); - } - head(requestUrl, additionalHeaders) { - return this.request('HEAD', requestUrl, null, additionalHeaders || {}); - } - sendStream(verb, requestUrl, stream, additionalHeaders) { - return this.request(verb, requestUrl, stream, additionalHeaders); - } - /** - * Gets a typed object from an endpoint - * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise - */ - async getJson(requestUrl, additionalHeaders = {}) { - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - let res = await this.get(requestUrl, additionalHeaders); - return this._processResponse(res, this.requestOptions); - } - async postJson(requestUrl, obj, additionalHeaders = {}) { - let data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - let res = await this.post(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - } - async putJson(requestUrl, obj, additionalHeaders = {}) { - let data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - let res = await this.put(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - } - async patchJson(requestUrl, obj, additionalHeaders = {}) { - let data = JSON.stringify(obj, null, 2); - additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); - additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); - let res = await this.patch(requestUrl, data, additionalHeaders); - return this._processResponse(res, this.requestOptions); - } - /** - * Makes a raw http request. - * All other methods such as get, post, patch, and request ultimately call this. - * Prefer get, del, post and patch - */ - async request(verb, requestUrl, data, headers) { - if (this._disposed) { - throw new Error('Client has already been disposed.'); - } - let parsedUrl = url.parse(requestUrl); - let info = this._prepareRequest(verb, parsedUrl, headers); - // Only perform retries on reads since writes may not be idempotent. - let maxTries = this._allowRetries && RetryableHttpVerbs.indexOf(verb) != -1 - ? this._maxRetries + 1 - : 1; - let numTries = 0; - let response; - while (numTries < maxTries) { - response = await this.requestRaw(info, data); - // Check if it's an authentication challenge - if (response && - response.message && - response.message.statusCode === HttpCodes.Unauthorized) { - let authenticationHandler; - for (let i = 0; i < this.handlers.length; i++) { - if (this.handlers[i].canHandleAuthentication(response)) { - authenticationHandler = this.handlers[i]; - break; - } - } - if (authenticationHandler) { - return authenticationHandler.handleAuthentication(this, info, data); - } - else { - // We have received an unauthorized response but have no handlers to handle it. - // Let the response return to the caller. - return response; - } - } - let redirectsRemaining = this._maxRedirects; - while (HttpRedirectCodes.indexOf(response.message.statusCode) != -1 && - this._allowRedirects && - redirectsRemaining > 0) { - const redirectUrl = response.message.headers['location']; - if (!redirectUrl) { - // if there's no location to redirect to, we won't - break; - } - let parsedRedirectUrl = url.parse(redirectUrl); - if (parsedUrl.protocol == 'https:' && - parsedUrl.protocol != parsedRedirectUrl.protocol && - !this._allowRedirectDowngrade) { - throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); - } - // we need to finish reading the response before reassigning response - // which will leak the open socket. - await response.readBody(); - // strip authorization header if redirected to a different hostname - if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { - for (let header in headers) { - // header names are case insensitive - if (header.toLowerCase() === 'authorization') { - delete headers[header]; - } - } - } - // let's make the request with the new redirectUrl - info = this._prepareRequest(verb, parsedRedirectUrl, headers); - response = await this.requestRaw(info, data); - redirectsRemaining--; - } - if (HttpResponseRetryCodes.indexOf(response.message.statusCode) == -1) { - // If not a retry code, return immediately instead of retrying - return response; - } - numTries += 1; - if (numTries < maxTries) { - await response.readBody(); - await this._performExponentialBackoff(numTries); - } - } - return response; - } - /** - * Needs to be called if keepAlive is set to true in request options. - */ - dispose() { - if (this._agent) { - this._agent.destroy(); - } - this._disposed = true; - } - /** - * Raw request. - * @param info - * @param data - */ - requestRaw(info, data) { - return new Promise((resolve, reject) => { - let callbackForResult = function (err, res) { - if (err) { - reject(err); - } - resolve(res); - }; - this.requestRawWithCallback(info, data, callbackForResult); - }); - } - /** - * Raw request with callback. - * @param info - * @param data - * @param onResult - */ - requestRawWithCallback(info, data, onResult) { - let socket; - if (typeof data === 'string') { - info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); - } - let callbackCalled = false; - let handleResult = (err, res) => { - if (!callbackCalled) { - callbackCalled = true; - onResult(err, res); - } - }; - let req = info.httpModule.request(info.options, (msg) => { - let res = new HttpClientResponse(msg); - handleResult(null, res); - }); - req.on('socket', sock => { - socket = sock; - }); - // If we ever get disconnected, we want the socket to timeout eventually - req.setTimeout(this._socketTimeout || 3 * 60000, () => { - if (socket) { - socket.end(); - } - handleResult(new Error('Request timeout: ' + info.options.path), null); - }); - req.on('error', function (err) { - // err has statusCode property - // res should have headers - handleResult(err, null); - }); - if (data && typeof data === 'string') { - req.write(data, 'utf8'); - } - if (data && typeof data !== 'string') { - data.on('close', function () { - req.end(); - }); - data.pipe(req); - } - else { - req.end(); - } - } - /** - * Gets an http agent. This function is useful when you need an http agent that handles - * routing through a proxy server - depending upon the url and proxy environment variables. - * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com - */ - getAgent(serverUrl) { - let parsedUrl = url.parse(serverUrl); - return this._getAgent(parsedUrl); - } - _prepareRequest(method, requestUrl, headers) { - const info = {}; - info.parsedUrl = requestUrl; - const usingSsl = info.parsedUrl.protocol === 'https:'; - info.httpModule = usingSsl ? https : http; - const defaultPort = usingSsl ? 443 : 80; - info.options = {}; - info.options.host = info.parsedUrl.hostname; - info.options.port = info.parsedUrl.port - ? parseInt(info.parsedUrl.port) - : defaultPort; - info.options.path = - (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); - info.options.method = method; - info.options.headers = this._mergeHeaders(headers); - if (this.userAgent != null) { - info.options.headers['user-agent'] = this.userAgent; - } - info.options.agent = this._getAgent(info.parsedUrl); - // gives handlers an opportunity to participate - if (this.handlers) { - this.handlers.forEach(handler => { - handler.prepareRequest(info.options); - }); - } - return info; - } - _mergeHeaders(headers) { - const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); - if (this.requestOptions && this.requestOptions.headers) { - return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers)); - } - return lowercaseKeys(headers || {}); - } - _getExistingOrDefaultHeader(additionalHeaders, header, _default) { - const lowercaseKeys = obj => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); - let clientHeader; - if (this.requestOptions && this.requestOptions.headers) { - clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; - } - return additionalHeaders[header] || clientHeader || _default; - } - _getAgent(parsedUrl) { - let agent; - let proxyUrl = pm.getProxyUrl(parsedUrl); - let useProxy = proxyUrl && proxyUrl.hostname; - if (this._keepAlive && useProxy) { - agent = this._proxyAgent; - } - if (this._keepAlive && !useProxy) { - agent = this._agent; - } - // if agent is already assigned use that agent. - if (!!agent) { - return agent; - } - const usingSsl = parsedUrl.protocol === 'https:'; - let maxSockets = 100; - if (!!this.requestOptions) { - maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; - } - if (useProxy) { - // If using proxy, need tunnel - if (!tunnel) { - tunnel = __webpack_require__(413); - } - const agentOptions = { - maxSockets: maxSockets, - keepAlive: this._keepAlive, - proxy: { - proxyAuth: proxyUrl.auth, - host: proxyUrl.hostname, - port: proxyUrl.port - } - }; - let tunnelAgent; - const overHttps = proxyUrl.protocol === 'https:'; - if (usingSsl) { - tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; - } - else { - tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; - } - agent = tunnelAgent(agentOptions); - this._proxyAgent = agent; - } - // if reusing agent across request and tunneling agent isn't assigned create a new agent - if (this._keepAlive && !agent) { - const options = { keepAlive: this._keepAlive, maxSockets: maxSockets }; - agent = usingSsl ? new https.Agent(options) : new http.Agent(options); - this._agent = agent; - } - // if not using private agent and tunnel agent isn't setup then use global agent - if (!agent) { - agent = usingSsl ? https.globalAgent : http.globalAgent; - } - if (usingSsl && this._ignoreSslError) { - // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process - // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options - // we have to cast it to any and change it directly - agent.options = Object.assign(agent.options || {}, { - rejectUnauthorized: false - }); - } - return agent; - } - _performExponentialBackoff(retryNumber) { - retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); - const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); - return new Promise(resolve => setTimeout(() => resolve(), ms)); - } - static dateTimeDeserializer(key, value) { - if (typeof value === 'string') { - let a = new Date(value); - if (!isNaN(a.valueOf())) { - return a; - } - } - return value; - } - async _processResponse(res, options) { - return new Promise(async (resolve, reject) => { - const statusCode = res.message.statusCode; - const response = { - statusCode: statusCode, - result: null, - headers: {} - }; - // not found leads to null obj returned - if (statusCode == HttpCodes.NotFound) { - resolve(response); - } - let obj; - let contents; - // get the result from the body - try { - contents = await res.readBody(); - if (contents && contents.length > 0) { - if (options && options.deserializeDates) { - obj = JSON.parse(contents, HttpClient.dateTimeDeserializer); + catch (e) { + if (e.message && e.message.includes(ERROR_PR_REVIEW_FROM_AUTHOR)) { + core.warning(ERROR_PR_REVIEW_FROM_AUTHOR); } else { - obj = JSON.parse(contents); + throw e; } - response.result = obj; } - response.headers = res.message.headers; - } - catch (err) { - // Invalid resource (contents not json); leaving result obj null - } - // note that 3xx redirects are handled by the http layer. - if (statusCode > 299) { - let msg; - // if exception/error in body, attempt to get better error - if (obj && obj.message) { - msg = obj.message; - } - else if (contents && contents.length > 0) { - // it may be the case that the exception is in the body message as string - msg = contents; - } - else { - msg = 'Failed request: (' + statusCode + ')'; - } - let err = new Error(msg); - // attach statusCode and body obj (if available) to the error object - err['statusCode'] = statusCode; - if (response.result) { - err['result'] = response.result; - } - reject(err); - } - else { - resolve(response); } }); } } -exports.HttpClient = HttpClient; +exports.GitHubHelper = GitHubHelper; /***/ }), -/***/ 605: -/***/ (function(module) { - -module.exports = require("http"); - -/***/ }), - -/***/ 614: -/***/ (function(module) { - -module.exports = require("events"); - -/***/ }), - -/***/ 622: -/***/ (function(module) { - -module.exports = require("path"); - -/***/ }), - -/***/ 631: -/***/ (function(module) { - -module.exports = require("net"); - -/***/ }), - -/***/ 669: -/***/ (function(module) { - -module.exports = require("util"); - -/***/ }), - -/***/ 672: +/***/ 723: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { @@ -4657,223 +8167,197 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; -var _a; Object.defineProperty(exports, "__esModule", { value: true }); -const assert_1 = __webpack_require__(357); -const fs = __webpack_require__(747); -const path = __webpack_require__(622); -_a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; -exports.IS_WINDOWS = process.platform === 'win32'; -function exists(fsPath) { - return __awaiter(this, void 0, void 0, function* () { - try { - yield exports.stat(fsPath); - } - catch (err) { - if (err.code === 'ENOENT') { - return false; - } - throw err; - } - return true; - }); -} -exports.exists = exists; -function isDirectory(fsPath, useStat = false) { - return __awaiter(this, void 0, void 0, function* () { - const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); - return stats.isDirectory(); - }); -} -exports.isDirectory = isDirectory; -/** - * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: - * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). - */ -function isRooted(p) { - p = normalizeSeparators(p); - if (!p) { - throw new Error('isRooted() parameter "p" cannot be empty'); +exports.GitIdentityHelper = void 0; +const core = __importStar(__webpack_require__(470)); +const git_config_helper_1 = __webpack_require__(468); +const utils = __importStar(__webpack_require__(611)); +// Default the committer and author to the GitHub Actions bot +const DEFAULT_COMMITTER = 'GitHub '; +const DEFAULT_AUTHOR = 'github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>'; +class GitIdentityHelper { + constructor(git) { + this.git = git; } - if (exports.IS_WINDOWS) { - return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello - ); // e.g. C: or C:\hello + getGitIdentityFromConfig() { + return __awaiter(this, void 0, void 0, function* () { + const gitConfigHelper = new git_config_helper_1.GitConfigHelper(this.git); + if ((yield gitConfigHelper.configOptionExists('user.name')) && + (yield gitConfigHelper.configOptionExists('user.email'))) { + const userName = yield gitConfigHelper.getConfigOption('user.name'); + const userEmail = yield gitConfigHelper.getConfigOption('user.email'); + return { + authorName: userName.value, + authorEmail: userEmail.value, + committerName: userName.value, + committerEmail: userEmail.value + }; + } + if ((yield gitConfigHelper.configOptionExists('committer.name')) && + (yield gitConfigHelper.configOptionExists('committer.email')) && + (yield gitConfigHelper.configOptionExists('author.name')) && + (yield gitConfigHelper.configOptionExists('author.email'))) { + const committerName = yield gitConfigHelper.getConfigOption('committer.name'); + const committerEmail = yield gitConfigHelper.getConfigOption('committer.email'); + const authorName = yield gitConfigHelper.getConfigOption('author.name'); + const authorEmail = yield gitConfigHelper.getConfigOption('author.email'); + return { + authorName: authorName.value, + authorEmail: authorEmail.value, + committerName: committerName.value, + committerEmail: committerEmail.value + }; + } + return undefined; + }); } - return p.startsWith('/'); -} -exports.isRooted = isRooted; -/** - * Recursively create a directory at `fsPath`. - * - * This implementation is optimistic, meaning it attempts to create the full - * path first, and backs up the path stack from there. - * - * @param fsPath The path to create - * @param maxDepth The maximum recursion depth - * @param depth The current recursion depth - */ -function mkdirP(fsPath, maxDepth = 1000, depth = 1) { - return __awaiter(this, void 0, void 0, function* () { - assert_1.ok(fsPath, 'a path argument must be provided'); - fsPath = path.resolve(fsPath); - if (depth >= maxDepth) - return exports.mkdir(fsPath); - try { - yield exports.mkdir(fsPath); - return; - } - catch (err) { - switch (err.code) { - case 'ENOENT': { - yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1); - yield exports.mkdir(fsPath); - return; - } - default: { - let stats; - try { - stats = yield exports.stat(fsPath); - } - catch (err2) { - throw err; - } - if (!stats.isDirectory()) - throw err; + getIdentity(author, committer) { + return __awaiter(this, void 0, void 0, function* () { + // If either committer or author is supplied they will be cross used + if (!committer && author) { + core.info('Supplied author will also be used as the committer.'); + committer = author; + } + if (!author && committer) { + core.info('Supplied committer will also be used as the author.'); + author = committer; + } + // If no committer/author has been supplied, try and fetch identity + // configuration already existing in git config. + if (!committer && !author) { + const identity = yield this.getGitIdentityFromConfig(); + if (identity) { + core.info('Retrieved a pre-configured git identity.'); + return identity; } } - } - }); -} -exports.mkdirP = mkdirP; -/** - * Best effort attempt to determine whether a file exists and is executable. - * @param filePath file path to check - * @param extensions additional file extensions to try - * @return if file exists and is executable, returns the file path. otherwise empty string. - */ -function tryGetExecutablePath(filePath, extensions) { - return __awaiter(this, void 0, void 0, function* () { - let stats = undefined; - try { - // test file exists - stats = yield exports.stat(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + // Set defaults if no committer/author has been supplied and no + // existing identity configuration was found. + if (!committer && !author) { + core.info('Action defaults set for the author and committer.'); + committer = DEFAULT_COMMITTER; + author = DEFAULT_AUTHOR; } - } - if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // on Windows, test for valid extension - const upperExt = path.extname(filePath).toUpperCase(); - if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { - return filePath; - } - } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - // try each extension - const originalFilePath = filePath; - for (const extension of extensions) { - filePath = originalFilePath + extension; - stats = undefined; - try { - stats = yield exports.stat(filePath); - } - catch (err) { - if (err.code !== 'ENOENT') { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); - } - } - if (stats && stats.isFile()) { - if (exports.IS_WINDOWS) { - // preserve the case of the actual file (since an extension was appended) - try { - const directory = path.dirname(filePath); - const upperName = path.basename(filePath).toUpperCase(); - for (const actualName of yield exports.readdir(directory)) { - if (upperName === actualName.toUpperCase()) { - filePath = path.join(directory, actualName); - break; - } - } - } - catch (err) { - // eslint-disable-next-line no-console - console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); - } - return filePath; - } - else { - if (isUnixExecutable(stats)) { - return filePath; - } - } - } - } - return ''; - }); -} -exports.tryGetExecutablePath = tryGetExecutablePath; -function normalizeSeparators(p) { - p = p || ''; - if (exports.IS_WINDOWS) { - // convert slashes on Windows - p = p.replace(/\//g, '\\'); - // remove redundant slashes - return p.replace(/\\\\+/g, '\\'); + const parsedAuthor = utils.parseDisplayNameEmail(author); + const parsedCommitter = utils.parseDisplayNameEmail(committer); + return { + authorName: parsedAuthor.name, + authorEmail: parsedAuthor.email, + committerName: parsedCommitter.name, + committerEmail: parsedCommitter.email + }; + }); } - // remove redundant slashes - return p.replace(/\/\/+/g, '/'); } -// on Mac/Linux, test the execute bit -// R W X R W X R W X -// 256 128 64 32 16 8 4 2 1 -function isUnixExecutable(stats) { - return ((stats.mode & 1) > 0 || - ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || - ((stats.mode & 64) > 0 && stats.uid === process.getuid())); -} -//# sourceMappingURL=io-util.js.map +exports.GitIdentityHelper = GitIdentityHelper; + /***/ }), -/***/ 722: -/***/ (function(module) { +/***/ 733: +/***/ (function(__unusedmodule, exports, __webpack_require__) { -/** - * Convert array of 16 byte values to UUID string format of the form: - * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - */ -var byteToHex = []; -for (var i = 0; i < 256; ++i) { - byteToHex[i] = (i + 0x100).toString(16).substr(1); +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _rng = _interopRequireDefault(__webpack_require__(844)); + +var _bytesToUuid = _interopRequireDefault(__webpack_require__(390)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _bytesToUuid.default)(rnds); } -function bytesToUuid(buf, offset) { - var i = offset || 0; - var bth = byteToHex; - // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4 - return ([ - bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], '-', - bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]], - bth[buf[i++]], bth[buf[i++]] - ]).join(''); +var _default = v4; +exports.default = _default; + +/***/ }), + +/***/ 742: +/***/ (function(module, __unusedexports, __webpack_require__) { + +var fs = __webpack_require__(747) +var core +if (process.platform === 'win32' || global.TESTING_WINDOWS) { + core = __webpack_require__(818) +} else { + core = __webpack_require__(197) } -module.exports = bytesToUuid; +module.exports = isexe +isexe.sync = sync + +function isexe (path, options, cb) { + if (typeof options === 'function') { + cb = options + options = {} + } + + if (!cb) { + if (typeof Promise !== 'function') { + throw new TypeError('callback not provided') + } + + return new Promise(function (resolve, reject) { + isexe(path, options || {}, function (er, is) { + if (er) { + reject(er) + } else { + resolve(is) + } + }) + }) + } + + core(path, options || {}, function (er, is) { + // ignore EACCES because that just means we aren't allowed to run it + if (er) { + if (er.code === 'EACCES' || options && options.ignoreErrors) { + er = null + is = false + } + } + cb(er, is) + }) +} + +function sync (path, options) { + // my kingdom for a filtered catch + try { + return core.sync(path, options || {}) + } catch (er) { + if (options && options.ignoreErrors || er.code === 'EACCES') { + return false + } else { + throw er + } + } +} /***/ }), @@ -4885,45 +8369,454 @@ module.exports = require("fs"); /***/ }), -/***/ 794: -/***/ (function(module) { +/***/ 753: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var endpoint = __webpack_require__(385); +var universalUserAgent = __webpack_require__(796); +var isPlainObject = _interopDefault(__webpack_require__(548)); +var nodeFetch = _interopDefault(__webpack_require__(454)); +var requestError = __webpack_require__(463); + +const VERSION = "5.4.5"; + +function getBufferResponse(response) { + return response.arrayBuffer(); +} + +function fetchWrapper(requestOptions) { + if (isPlainObject(requestOptions.body) || Array.isArray(requestOptions.body)) { + requestOptions.body = JSON.stringify(requestOptions.body); + } + + let headers = {}; + let status; + let url; + const fetch = requestOptions.request && requestOptions.request.fetch || nodeFetch; + return fetch(requestOptions.url, Object.assign({ + method: requestOptions.method, + body: requestOptions.body, + headers: requestOptions.headers, + redirect: requestOptions.redirect + }, requestOptions.request)).then(response => { + url = response.url; + status = response.status; + + for (const keyAndValue of response.headers) { + headers[keyAndValue[0]] = keyAndValue[1]; + } + + if (status === 204 || status === 205) { + return; + } // GitHub API returns 200 for HEAD requests + + + if (requestOptions.method === "HEAD") { + if (status < 400) { + return; + } + + throw new requestError.RequestError(response.statusText, status, { + headers, + request: requestOptions + }); + } + + if (status === 304) { + throw new requestError.RequestError("Not modified", status, { + headers, + request: requestOptions + }); + } + + if (status >= 400) { + return response.text().then(message => { + const error = new requestError.RequestError(message, status, { + headers, + request: requestOptions + }); + + try { + let responseBody = JSON.parse(error.message); + Object.assign(error, responseBody); + let errors = responseBody.errors; // Assumption `errors` would always be in Array format + + error.message = error.message + ": " + errors.map(JSON.stringify).join(", "); + } catch (e) {// ignore, see octokit/rest.js#684 + } + + throw error; + }); + } + + const contentType = response.headers.get("content-type"); + + if (/application\/json/.test(contentType)) { + return response.json(); + } + + if (!contentType || /^text\/|charset=utf-8$/.test(contentType)) { + return response.text(); + } + + return getBufferResponse(response); + }).then(data => { + return { + status, + url, + headers, + data + }; + }).catch(error => { + if (error instanceof requestError.RequestError) { + throw error; + } + + throw new requestError.RequestError(error.message, 500, { + headers, + request: requestOptions + }); + }); +} + +function withDefaults(oldEndpoint, newDefaults) { + const endpoint = oldEndpoint.defaults(newDefaults); + + const newApi = function (route, parameters) { + const endpointOptions = endpoint.merge(route, parameters); + + if (!endpointOptions.request || !endpointOptions.request.hook) { + return fetchWrapper(endpoint.parse(endpointOptions)); + } + + const request = (route, parameters) => { + return fetchWrapper(endpoint.parse(endpoint.merge(route, parameters))); + }; + + Object.assign(request, { + endpoint, + defaults: withDefaults.bind(null, endpoint) + }); + return endpointOptions.request.hook(request, endpointOptions); + }; + + return Object.assign(newApi, { + endpoint, + defaults: withDefaults.bind(null, endpoint) + }); +} + +const request = withDefaults(endpoint.endpoint, { + headers: { + "user-agent": `octokit-request.js/${VERSION} ${universalUserAgent.getUserAgent()}` + } +}); + +exports.request = request; +//# sourceMappingURL=index.js.map -module.exports = require("stream"); /***/ }), -/***/ 826: -/***/ (function(module, __unusedexports, __webpack_require__) { +/***/ 759: +/***/ (function(module) { -var rng = __webpack_require__(139); -var bytesToUuid = __webpack_require__(722); +"use strict"; -function v4(options, buf, offset) { - var i = buf && offset || 0; - if (typeof(options) == 'string') { - buf = options === 'binary' ? new Array(16) : null; - options = null; - } - options = options || {}; +// See http://www.robvanderwoude.com/escapechars.php +const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; - var rnds = options.random || (options.rng || rng)(); +function escapeCommand(arg) { + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); - // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` - rnds[6] = (rnds[6] & 0x0f) | 0x40; - rnds[8] = (rnds[8] & 0x3f) | 0x80; - - // Copy bytes to buffer, if provided - if (buf) { - for (var ii = 0; ii < 16; ++ii) { - buf[i + ii] = rnds[ii]; - } - } - - return buf || bytesToUuid(rnds); + return arg; } -module.exports = v4; +function escapeArgument(arg, doubleEscapeMetaChars) { + // Convert to string + arg = `${arg}`; + + // Algorithm below is based on https://qntm.org/cmd + + // Sequence of backslashes followed by a double quote: + // double up all the backslashes and escape the double quote + arg = arg.replace(/(\\*)"/g, '$1$1\\"'); + + // Sequence of backslashes followed by the end of the string + // (which will become a double quote later): + // double up all the backslashes + arg = arg.replace(/(\\*)$/, '$1$1'); + + // All other backslashes occur literally + + // Quote the whole thing: + arg = `"${arg}"`; + + // Escape meta chars + arg = arg.replace(metaCharsRegExp, '^$1'); + + // Double escape meta chars if necessary + if (doubleEscapeMetaChars) { + arg = arg.replace(metaCharsRegExp, '^$1'); + } + + return arg; +} + +module.exports.command = escapeCommand; +module.exports.argument = escapeArgument; + + +/***/ }), + +/***/ 761: +/***/ (function(module) { + +module.exports = require("zlib"); + +/***/ }), + +/***/ 768: +/***/ (function(module) { + +"use strict"; + +module.exports = function (x) { + var lf = typeof x === 'string' ? '\n' : '\n'.charCodeAt(); + var cr = typeof x === 'string' ? '\r' : '\r'.charCodeAt(); + + if (x[x.length - 1] === lf) { + x = x.slice(0, x.length - 1); + } + + if (x[x.length - 1] === cr) { + x = x.slice(0, x.length - 1); + } + + return x; +}; + + +/***/ }), + +/***/ 774: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + + +const cp = __webpack_require__(129); +const parse = __webpack_require__(884); +const enoent = __webpack_require__(15); + +function spawn(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); + + // Spawn the child process + const spawned = cp.spawn(parsed.command, parsed.args, parsed.options); + + // Hook into child process "exit" event to emit an error if the command + // does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + enoent.hookChildProcess(spawned, parsed); + + return spawned; +} + +function spawnSync(command, args, options) { + // Parse the arguments + const parsed = parse(command, args, options); + + // Spawn the child process + const result = cp.spawnSync(parsed.command, parsed.args, parsed.options); + + // Analyze if the command does not exist, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16 + result.error = result.error || enoent.verifyENOENTSync(result.status, parsed); + + return result; +} + +module.exports = spawn; +module.exports.spawn = spawn; +module.exports.sync = spawnSync; + +module.exports._parse = parse; +module.exports._enoent = enoent; + + +/***/ }), + +/***/ 796: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var osName = _interopDefault(__webpack_require__(2)); + +function getUserAgent() { + try { + return `Node.js/${process.version.substr(1)} (${osName()}; ${process.arch})`; + } catch (error) { + if (/wmic os get Caption/.test(error.message)) { + return "Windows "; + } + + return ""; + } +} + +exports.getUserAgent = getUserAgent; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 803: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _crypto = _interopRequireDefault(__webpack_require__(417)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports.default = _default; + +/***/ }), + +/***/ 813: +/***/ (function(__unusedmodule, exports) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +async function auth(token) { + const tokenType = token.split(/\./).length === 3 ? "app" : /^v\d+\./.test(token) ? "installation" : "oauth"; + return { + type: "token", + token: token, + tokenType + }; +} + +/** + * Prefix token for usage in the Authorization header + * + * @param token OAuth token or JSON Web Token + */ +function withAuthorizationPrefix(token) { + if (token.split(/\./).length === 3) { + return `bearer ${token}`; + } + + return `token ${token}`; +} + +async function hook(token, request, route, parameters) { + const endpoint = request.endpoint.merge(route, parameters); + endpoint.headers.authorization = withAuthorizationPrefix(token); + return request(endpoint); +} + +const createTokenAuth = function createTokenAuth(token) { + if (!token) { + throw new Error("[@octokit/auth-token] No token passed to createTokenAuth"); + } + + if (typeof token !== "string") { + throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string"); + } + + token = token.replace(/^(token|bearer) +/i, ""); + return Object.assign(auth.bind(null, token), { + hook: hook.bind(null, token) + }); +}; + +exports.createTokenAuth = createTokenAuth; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 818: +/***/ (function(module, __unusedexports, __webpack_require__) { + +module.exports = isexe +isexe.sync = sync + +var fs = __webpack_require__(747) + +function checkPathExt (path, options) { + var pathext = options.pathExt !== undefined ? + options.pathExt : process.env.PATHEXT + + if (!pathext) { + return true + } + + pathext = pathext.split(';') + if (pathext.indexOf('') !== -1) { + return true + } + for (var i = 0; i < pathext.length; i++) { + var p = pathext[i].toLowerCase() + if (p && path.substr(-p.length).toLowerCase() === p) { + return true + } + } + return false +} + +function checkStat (stat, path, options) { + if (!stat.isSymbolicLink() && !stat.isFile()) { + return false + } + return checkPathExt(path, options) +} + +function isexe (path, options, cb) { + fs.stat(path, function (er, stat) { + cb(er, er ? false : checkStat(stat, path, options)) + }) +} + +function sync (path, options) { + return checkStat(fs.statSync(path), path, options) +} /***/ }), @@ -4935,73 +8828,1626 @@ module.exports = require("url"); /***/ }), -/***/ 950: +/***/ 842: +/***/ (function(__unusedmodule, exports) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +const Endpoints = { + actions: { + addSelectedRepoToOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"], + cancelWorkflowRun: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel"], + createOrUpdateOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}"], + createOrUpdateRepoSecret: ["PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}"], + createRegistrationTokenForOrg: ["POST /orgs/{org}/actions/runners/registration-token"], + createRegistrationTokenForRepo: ["POST /repos/{owner}/{repo}/actions/runners/registration-token"], + createRemoveTokenForOrg: ["POST /orgs/{org}/actions/runners/remove-token"], + createRemoveTokenForRepo: ["POST /repos/{owner}/{repo}/actions/runners/remove-token"], + deleteArtifact: ["DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"], + deleteOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}"], + deleteRepoSecret: ["DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}"], + deleteSelfHostedRunnerFromOrg: ["DELETE /orgs/{org}/actions/runners/{runner_id}"], + deleteSelfHostedRunnerFromRepo: ["DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}"], + deleteWorkflowRunLogs: ["DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs"], + downloadArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}"], + downloadJobLogsForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs"], + downloadWorkflowRunLogs: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs"], + getArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"], + getJobForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}"], + getOrgPublicKey: ["GET /orgs/{org}/actions/secrets/public-key"], + getOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}"], + getRepoPublicKey: ["GET /repos/{owner}/{repo}/actions/secrets/public-key"], + getRepoSecret: ["GET /repos/{owner}/{repo}/actions/secrets/{secret_name}"], + getSelfHostedRunnerForOrg: ["GET /orgs/{org}/actions/runners/{runner_id}"], + getSelfHostedRunnerForRepo: ["GET /repos/{owner}/{repo}/actions/runners/{runner_id}"], + getWorkflow: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}"], + getWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}"], + getWorkflowRunUsage: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing"], + getWorkflowUsage: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing"], + listArtifactsForRepo: ["GET /repos/{owner}/{repo}/actions/artifacts"], + listJobsForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs"], + listOrgSecrets: ["GET /orgs/{org}/actions/secrets"], + listRepoSecrets: ["GET /repos/{owner}/{repo}/actions/secrets"], + listRepoWorkflows: ["GET /repos/{owner}/{repo}/actions/workflows"], + listRunnerApplicationsForOrg: ["GET /orgs/{org}/actions/runners/downloads"], + listRunnerApplicationsForRepo: ["GET /repos/{owner}/{repo}/actions/runners/downloads"], + listSelectedReposForOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}/repositories"], + listSelfHostedRunnersForOrg: ["GET /orgs/{org}/actions/runners"], + listSelfHostedRunnersForRepo: ["GET /repos/{owner}/{repo}/actions/runners"], + listWorkflowRunArtifacts: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts"], + listWorkflowRuns: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs"], + listWorkflowRunsForRepo: ["GET /repos/{owner}/{repo}/actions/runs"], + reRunWorkflow: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun"], + removeSelectedRepoFromOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"], + setSelectedReposForOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}/repositories"] + }, + activity: { + checkRepoIsStarredByAuthenticatedUser: ["GET /user/starred/{owner}/{repo}"], + deleteRepoSubscription: ["DELETE /repos/{owner}/{repo}/subscription"], + deleteThreadSubscription: ["DELETE /notifications/threads/{thread_id}/subscription"], + getFeeds: ["GET /feeds"], + getRepoSubscription: ["GET /repos/{owner}/{repo}/subscription"], + getThread: ["GET /notifications/threads/{thread_id}"], + getThreadSubscriptionForAuthenticatedUser: ["GET /notifications/threads/{thread_id}/subscription"], + listEventsForAuthenticatedUser: ["GET /users/{username}/events"], + listNotificationsForAuthenticatedUser: ["GET /notifications"], + listOrgEventsForAuthenticatedUser: ["GET /users/{username}/events/orgs/{org}"], + listPublicEvents: ["GET /events"], + listPublicEventsForRepoNetwork: ["GET /networks/{owner}/{repo}/events"], + listPublicEventsForUser: ["GET /users/{username}/events/public"], + listPublicOrgEvents: ["GET /orgs/{org}/events"], + listReceivedEventsForUser: ["GET /users/{username}/received_events"], + listReceivedPublicEventsForUser: ["GET /users/{username}/received_events/public"], + listRepoEvents: ["GET /repos/{owner}/{repo}/events"], + listRepoNotificationsForAuthenticatedUser: ["GET /repos/{owner}/{repo}/notifications"], + listReposStarredByAuthenticatedUser: ["GET /user/starred"], + listReposStarredByUser: ["GET /users/{username}/starred"], + listReposWatchedByUser: ["GET /users/{username}/subscriptions"], + listStargazersForRepo: ["GET /repos/{owner}/{repo}/stargazers"], + listWatchedReposForAuthenticatedUser: ["GET /user/subscriptions"], + listWatchersForRepo: ["GET /repos/{owner}/{repo}/subscribers"], + markNotificationsAsRead: ["PUT /notifications"], + markRepoNotificationsAsRead: ["PUT /repos/{owner}/{repo}/notifications"], + markThreadAsRead: ["PATCH /notifications/threads/{thread_id}"], + setRepoSubscription: ["PUT /repos/{owner}/{repo}/subscription"], + setThreadSubscription: ["PUT /notifications/threads/{thread_id}/subscription"], + starRepoForAuthenticatedUser: ["PUT /user/starred/{owner}/{repo}"], + unstarRepoForAuthenticatedUser: ["DELETE /user/starred/{owner}/{repo}"] + }, + apps: { + addRepoToInstallation: ["PUT /user/installations/{installation_id}/repositories/{repository_id}", { + mediaType: { + previews: ["machine-man"] + } + }], + checkToken: ["POST /applications/{client_id}/token"], + createContentAttachment: ["POST /content_references/{content_reference_id}/attachments", { + mediaType: { + previews: ["corsair"] + } + }], + createFromManifest: ["POST /app-manifests/{code}/conversions"], + createInstallationAccessToken: ["POST /app/installations/{installation_id}/access_tokens", { + mediaType: { + previews: ["machine-man"] + } + }], + deleteAuthorization: ["DELETE /applications/{client_id}/grant"], + deleteInstallation: ["DELETE /app/installations/{installation_id}", { + mediaType: { + previews: ["machine-man"] + } + }], + deleteToken: ["DELETE /applications/{client_id}/token"], + getAuthenticated: ["GET /app", { + mediaType: { + previews: ["machine-man"] + } + }], + getBySlug: ["GET /apps/{app_slug}", { + mediaType: { + previews: ["machine-man"] + } + }], + getInstallation: ["GET /app/installations/{installation_id}", { + mediaType: { + previews: ["machine-man"] + } + }], + getOrgInstallation: ["GET /orgs/{org}/installation", { + mediaType: { + previews: ["machine-man"] + } + }], + getRepoInstallation: ["GET /repos/{owner}/{repo}/installation", { + mediaType: { + previews: ["machine-man"] + } + }], + getSubscriptionPlanForAccount: ["GET /marketplace_listing/accounts/{account_id}"], + getSubscriptionPlanForAccountStubbed: ["GET /marketplace_listing/stubbed/accounts/{account_id}"], + getUserInstallation: ["GET /users/{username}/installation", { + mediaType: { + previews: ["machine-man"] + } + }], + listAccountsForPlan: ["GET /marketplace_listing/plans/{plan_id}/accounts"], + listAccountsForPlanStubbed: ["GET /marketplace_listing/stubbed/plans/{plan_id}/accounts"], + listInstallationReposForAuthenticatedUser: ["GET /user/installations/{installation_id}/repositories", { + mediaType: { + previews: ["machine-man"] + } + }], + listInstallations: ["GET /app/installations", { + mediaType: { + previews: ["machine-man"] + } + }], + listInstallationsForAuthenticatedUser: ["GET /user/installations", { + mediaType: { + previews: ["machine-man"] + } + }], + listPlans: ["GET /marketplace_listing/plans"], + listPlansStubbed: ["GET /marketplace_listing/stubbed/plans"], + listReposAccessibleToInstallation: ["GET /installation/repositories", { + mediaType: { + previews: ["machine-man"] + } + }], + listSubscriptionsForAuthenticatedUser: ["GET /user/marketplace_purchases"], + listSubscriptionsForAuthenticatedUserStubbed: ["GET /user/marketplace_purchases/stubbed"], + removeRepoFromInstallation: ["DELETE /user/installations/{installation_id}/repositories/{repository_id}", { + mediaType: { + previews: ["machine-man"] + } + }], + resetToken: ["PATCH /applications/{client_id}/token"], + revokeInstallationAccessToken: ["DELETE /installation/token"], + suspendInstallation: ["PUT /app/installations/{installation_id}/suspended"], + unsuspendInstallation: ["DELETE /app/installations/{installation_id}/suspended"] + }, + checks: { + create: ["POST /repos/{owner}/{repo}/check-runs", { + mediaType: { + previews: ["antiope"] + } + }], + createSuite: ["POST /repos/{owner}/{repo}/check-suites", { + mediaType: { + previews: ["antiope"] + } + }], + get: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}", { + mediaType: { + previews: ["antiope"] + } + }], + getSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}", { + mediaType: { + previews: ["antiope"] + } + }], + listAnnotations: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations", { + mediaType: { + previews: ["antiope"] + } + }], + listForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-runs", { + mediaType: { + previews: ["antiope"] + } + }], + listForSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs", { + mediaType: { + previews: ["antiope"] + } + }], + listSuitesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-suites", { + mediaType: { + previews: ["antiope"] + } + }], + rerequestSuite: ["POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest", { + mediaType: { + previews: ["antiope"] + } + }], + setSuitesPreferences: ["PATCH /repos/{owner}/{repo}/check-suites/preferences", { + mediaType: { + previews: ["antiope"] + } + }], + update: ["PATCH /repos/{owner}/{repo}/check-runs/{check_run_id}", { + mediaType: { + previews: ["antiope"] + } + }] + }, + codeScanning: { + getAlert: ["GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_id}"], + listAlertsForRepo: ["GET /repos/{owner}/{repo}/code-scanning/alerts"] + }, + codesOfConduct: { + getAllCodesOfConduct: ["GET /codes_of_conduct", { + mediaType: { + previews: ["scarlet-witch"] + } + }], + getConductCode: ["GET /codes_of_conduct/{key}", { + mediaType: { + previews: ["scarlet-witch"] + } + }], + getForRepo: ["GET /repos/{owner}/{repo}/community/code_of_conduct", { + mediaType: { + previews: ["scarlet-witch"] + } + }] + }, + emojis: { + get: ["GET /emojis"] + }, + gists: { + checkIsStarred: ["GET /gists/{gist_id}/star"], + create: ["POST /gists"], + createComment: ["POST /gists/{gist_id}/comments"], + delete: ["DELETE /gists/{gist_id}"], + deleteComment: ["DELETE /gists/{gist_id}/comments/{comment_id}"], + fork: ["POST /gists/{gist_id}/forks"], + get: ["GET /gists/{gist_id}"], + getComment: ["GET /gists/{gist_id}/comments/{comment_id}"], + getRevision: ["GET /gists/{gist_id}/{sha}"], + list: ["GET /gists"], + listComments: ["GET /gists/{gist_id}/comments"], + listCommits: ["GET /gists/{gist_id}/commits"], + listForUser: ["GET /users/{username}/gists"], + listForks: ["GET /gists/{gist_id}/forks"], + listPublic: ["GET /gists/public"], + listStarred: ["GET /gists/starred"], + star: ["PUT /gists/{gist_id}/star"], + unstar: ["DELETE /gists/{gist_id}/star"], + update: ["PATCH /gists/{gist_id}"], + updateComment: ["PATCH /gists/{gist_id}/comments/{comment_id}"] + }, + git: { + createBlob: ["POST /repos/{owner}/{repo}/git/blobs"], + createCommit: ["POST /repos/{owner}/{repo}/git/commits"], + createRef: ["POST /repos/{owner}/{repo}/git/refs"], + createTag: ["POST /repos/{owner}/{repo}/git/tags"], + createTree: ["POST /repos/{owner}/{repo}/git/trees"], + deleteRef: ["DELETE /repos/{owner}/{repo}/git/refs/{ref}"], + getBlob: ["GET /repos/{owner}/{repo}/git/blobs/{file_sha}"], + getCommit: ["GET /repos/{owner}/{repo}/git/commits/{commit_sha}"], + getRef: ["GET /repos/{owner}/{repo}/git/ref/{ref}"], + getTag: ["GET /repos/{owner}/{repo}/git/tags/{tag_sha}"], + getTree: ["GET /repos/{owner}/{repo}/git/trees/{tree_sha}"], + listMatchingRefs: ["GET /repos/{owner}/{repo}/git/matching-refs/{ref}"], + updateRef: ["PATCH /repos/{owner}/{repo}/git/refs/{ref}"] + }, + gitignore: { + getAllTemplates: ["GET /gitignore/templates"], + getTemplate: ["GET /gitignore/templates/{name}"] + }, + interactions: { + getRestrictionsForOrg: ["GET /orgs/{org}/interaction-limits", { + mediaType: { + previews: ["sombra"] + } + }], + getRestrictionsForRepo: ["GET /repos/{owner}/{repo}/interaction-limits", { + mediaType: { + previews: ["sombra"] + } + }], + removeRestrictionsForOrg: ["DELETE /orgs/{org}/interaction-limits", { + mediaType: { + previews: ["sombra"] + } + }], + removeRestrictionsForRepo: ["DELETE /repos/{owner}/{repo}/interaction-limits", { + mediaType: { + previews: ["sombra"] + } + }], + setRestrictionsForOrg: ["PUT /orgs/{org}/interaction-limits", { + mediaType: { + previews: ["sombra"] + } + }], + setRestrictionsForRepo: ["PUT /repos/{owner}/{repo}/interaction-limits", { + mediaType: { + previews: ["sombra"] + } + }] + }, + issues: { + addAssignees: ["POST /repos/{owner}/{repo}/issues/{issue_number}/assignees"], + addLabels: ["POST /repos/{owner}/{repo}/issues/{issue_number}/labels"], + checkUserCanBeAssigned: ["GET /repos/{owner}/{repo}/assignees/{assignee}"], + create: ["POST /repos/{owner}/{repo}/issues"], + createComment: ["POST /repos/{owner}/{repo}/issues/{issue_number}/comments"], + createLabel: ["POST /repos/{owner}/{repo}/labels"], + createMilestone: ["POST /repos/{owner}/{repo}/milestones"], + deleteComment: ["DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}"], + deleteLabel: ["DELETE /repos/{owner}/{repo}/labels/{name}"], + deleteMilestone: ["DELETE /repos/{owner}/{repo}/milestones/{milestone_number}"], + get: ["GET /repos/{owner}/{repo}/issues/{issue_number}"], + getComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}"], + getEvent: ["GET /repos/{owner}/{repo}/issues/events/{event_id}"], + getLabel: ["GET /repos/{owner}/{repo}/labels/{name}"], + getMilestone: ["GET /repos/{owner}/{repo}/milestones/{milestone_number}"], + list: ["GET /issues"], + listAssignees: ["GET /repos/{owner}/{repo}/assignees"], + listComments: ["GET /repos/{owner}/{repo}/issues/{issue_number}/comments"], + listCommentsForRepo: ["GET /repos/{owner}/{repo}/issues/comments"], + listEvents: ["GET /repos/{owner}/{repo}/issues/{issue_number}/events"], + listEventsForRepo: ["GET /repos/{owner}/{repo}/issues/events"], + listEventsForTimeline: ["GET /repos/{owner}/{repo}/issues/{issue_number}/timeline", { + mediaType: { + previews: ["mockingbird"] + } + }], + listForAuthenticatedUser: ["GET /user/issues"], + listForOrg: ["GET /orgs/{org}/issues"], + listForRepo: ["GET /repos/{owner}/{repo}/issues"], + listLabelsForMilestone: ["GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels"], + listLabelsForRepo: ["GET /repos/{owner}/{repo}/labels"], + listLabelsOnIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/labels"], + listMilestones: ["GET /repos/{owner}/{repo}/milestones"], + lock: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/lock"], + removeAllLabels: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels"], + removeAssignees: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees"], + removeLabel: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}"], + setLabels: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/labels"], + unlock: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock"], + update: ["PATCH /repos/{owner}/{repo}/issues/{issue_number}"], + updateComment: ["PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}"], + updateLabel: ["PATCH /repos/{owner}/{repo}/labels/{name}"], + updateMilestone: ["PATCH /repos/{owner}/{repo}/milestones/{milestone_number}"] + }, + licenses: { + get: ["GET /licenses/{license}"], + getAllCommonlyUsed: ["GET /licenses"], + getForRepo: ["GET /repos/{owner}/{repo}/license"] + }, + markdown: { + render: ["POST /markdown"], + renderRaw: ["POST /markdown/raw", { + headers: { + "content-type": "text/plain; charset=utf-8" + } + }] + }, + meta: { + get: ["GET /meta"] + }, + migrations: { + cancelImport: ["DELETE /repos/{owner}/{repo}/import"], + deleteArchiveForAuthenticatedUser: ["DELETE /user/migrations/{migration_id}/archive", { + mediaType: { + previews: ["wyandotte"] + } + }], + deleteArchiveForOrg: ["DELETE /orgs/{org}/migrations/{migration_id}/archive", { + mediaType: { + previews: ["wyandotte"] + } + }], + downloadArchiveForOrg: ["GET /orgs/{org}/migrations/{migration_id}/archive", { + mediaType: { + previews: ["wyandotte"] + } + }], + getArchiveForAuthenticatedUser: ["GET /user/migrations/{migration_id}/archive", { + mediaType: { + previews: ["wyandotte"] + } + }], + getCommitAuthors: ["GET /repos/{owner}/{repo}/import/authors"], + getImportStatus: ["GET /repos/{owner}/{repo}/import"], + getLargeFiles: ["GET /repos/{owner}/{repo}/import/large_files"], + getStatusForAuthenticatedUser: ["GET /user/migrations/{migration_id}", { + mediaType: { + previews: ["wyandotte"] + } + }], + getStatusForOrg: ["GET /orgs/{org}/migrations/{migration_id}", { + mediaType: { + previews: ["wyandotte"] + } + }], + listForAuthenticatedUser: ["GET /user/migrations", { + mediaType: { + previews: ["wyandotte"] + } + }], + listForOrg: ["GET /orgs/{org}/migrations", { + mediaType: { + previews: ["wyandotte"] + } + }], + listReposForOrg: ["GET /orgs/{org}/migrations/{migration_id}/repositories", { + mediaType: { + previews: ["wyandotte"] + } + }], + listReposForUser: ["GET /user/{migration_id}/repositories", { + mediaType: { + previews: ["wyandotte"] + } + }], + mapCommitAuthor: ["PATCH /repos/{owner}/{repo}/import/authors/{author_id}"], + setLfsPreference: ["PATCH /repos/{owner}/{repo}/import/lfs"], + startForAuthenticatedUser: ["POST /user/migrations"], + startForOrg: ["POST /orgs/{org}/migrations"], + startImport: ["PUT /repos/{owner}/{repo}/import"], + unlockRepoForAuthenticatedUser: ["DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock", { + mediaType: { + previews: ["wyandotte"] + } + }], + unlockRepoForOrg: ["DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock", { + mediaType: { + previews: ["wyandotte"] + } + }], + updateImport: ["PATCH /repos/{owner}/{repo}/import"] + }, + orgs: { + blockUser: ["PUT /orgs/{org}/blocks/{username}"], + checkBlockedUser: ["GET /orgs/{org}/blocks/{username}"], + checkMembershipForUser: ["GET /orgs/{org}/members/{username}"], + checkPublicMembershipForUser: ["GET /orgs/{org}/public_members/{username}"], + convertMemberToOutsideCollaborator: ["PUT /orgs/{org}/outside_collaborators/{username}"], + createInvitation: ["POST /orgs/{org}/invitations"], + createWebhook: ["POST /orgs/{org}/hooks"], + deleteWebhook: ["DELETE /orgs/{org}/hooks/{hook_id}"], + get: ["GET /orgs/{org}"], + getMembershipForAuthenticatedUser: ["GET /user/memberships/orgs/{org}"], + getMembershipForUser: ["GET /orgs/{org}/memberships/{username}"], + getWebhook: ["GET /orgs/{org}/hooks/{hook_id}"], + list: ["GET /organizations"], + listAppInstallations: ["GET /orgs/{org}/installations", { + mediaType: { + previews: ["machine-man"] + } + }], + listBlockedUsers: ["GET /orgs/{org}/blocks"], + listForAuthenticatedUser: ["GET /user/orgs"], + listForUser: ["GET /users/{username}/orgs"], + listInvitationTeams: ["GET /orgs/{org}/invitations/{invitation_id}/teams"], + listMembers: ["GET /orgs/{org}/members"], + listMembershipsForAuthenticatedUser: ["GET /user/memberships/orgs"], + listOutsideCollaborators: ["GET /orgs/{org}/outside_collaborators"], + listPendingInvitations: ["GET /orgs/{org}/invitations"], + listPublicMembers: ["GET /orgs/{org}/public_members"], + listWebhooks: ["GET /orgs/{org}/hooks"], + pingWebhook: ["POST /orgs/{org}/hooks/{hook_id}/pings"], + removeMember: ["DELETE /orgs/{org}/members/{username}"], + removeMembershipForUser: ["DELETE /orgs/{org}/memberships/{username}"], + removeOutsideCollaborator: ["DELETE /orgs/{org}/outside_collaborators/{username}"], + removePublicMembershipForAuthenticatedUser: ["DELETE /orgs/{org}/public_members/{username}"], + setMembershipForUser: ["PUT /orgs/{org}/memberships/{username}"], + setPublicMembershipForAuthenticatedUser: ["PUT /orgs/{org}/public_members/{username}"], + unblockUser: ["DELETE /orgs/{org}/blocks/{username}"], + update: ["PATCH /orgs/{org}"], + updateMembershipForAuthenticatedUser: ["PATCH /user/memberships/orgs/{org}"], + updateWebhook: ["PATCH /orgs/{org}/hooks/{hook_id}"] + }, + projects: { + addCollaborator: ["PUT /projects/{project_id}/collaborators/{username}", { + mediaType: { + previews: ["inertia"] + } + }], + createCard: ["POST /projects/columns/{column_id}/cards", { + mediaType: { + previews: ["inertia"] + } + }], + createColumn: ["POST /projects/{project_id}/columns", { + mediaType: { + previews: ["inertia"] + } + }], + createForAuthenticatedUser: ["POST /user/projects", { + mediaType: { + previews: ["inertia"] + } + }], + createForOrg: ["POST /orgs/{org}/projects", { + mediaType: { + previews: ["inertia"] + } + }], + createForRepo: ["POST /repos/{owner}/{repo}/projects", { + mediaType: { + previews: ["inertia"] + } + }], + delete: ["DELETE /projects/{project_id}", { + mediaType: { + previews: ["inertia"] + } + }], + deleteCard: ["DELETE /projects/columns/cards/{card_id}", { + mediaType: { + previews: ["inertia"] + } + }], + deleteColumn: ["DELETE /projects/columns/{column_id}", { + mediaType: { + previews: ["inertia"] + } + }], + get: ["GET /projects/{project_id}", { + mediaType: { + previews: ["inertia"] + } + }], + getCard: ["GET /projects/columns/cards/{card_id}", { + mediaType: { + previews: ["inertia"] + } + }], + getColumn: ["GET /projects/columns/{column_id}", { + mediaType: { + previews: ["inertia"] + } + }], + getPermissionForUser: ["GET /projects/{project_id}/collaborators/{username}/permission", { + mediaType: { + previews: ["inertia"] + } + }], + listCards: ["GET /projects/columns/{column_id}/cards", { + mediaType: { + previews: ["inertia"] + } + }], + listCollaborators: ["GET /projects/{project_id}/collaborators", { + mediaType: { + previews: ["inertia"] + } + }], + listColumns: ["GET /projects/{project_id}/columns", { + mediaType: { + previews: ["inertia"] + } + }], + listForOrg: ["GET /orgs/{org}/projects", { + mediaType: { + previews: ["inertia"] + } + }], + listForRepo: ["GET /repos/{owner}/{repo}/projects", { + mediaType: { + previews: ["inertia"] + } + }], + listForUser: ["GET /users/{username}/projects", { + mediaType: { + previews: ["inertia"] + } + }], + moveCard: ["POST /projects/columns/cards/{card_id}/moves", { + mediaType: { + previews: ["inertia"] + } + }], + moveColumn: ["POST /projects/columns/{column_id}/moves", { + mediaType: { + previews: ["inertia"] + } + }], + removeCollaborator: ["DELETE /projects/{project_id}/collaborators/{username}", { + mediaType: { + previews: ["inertia"] + } + }], + update: ["PATCH /projects/{project_id}", { + mediaType: { + previews: ["inertia"] + } + }], + updateCard: ["PATCH /projects/columns/cards/{card_id}", { + mediaType: { + previews: ["inertia"] + } + }], + updateColumn: ["PATCH /projects/columns/{column_id}", { + mediaType: { + previews: ["inertia"] + } + }] + }, + pulls: { + checkIfMerged: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/merge"], + create: ["POST /repos/{owner}/{repo}/pulls"], + createReplyForReviewComment: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies"], + createReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], + createReviewComment: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/comments"], + deletePendingReview: ["DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], + deleteReviewComment: ["DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}"], + dismissReview: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals"], + get: ["GET /repos/{owner}/{repo}/pulls/{pull_number}"], + getReview: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], + getReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}"], + list: ["GET /repos/{owner}/{repo}/pulls"], + listCommentsForReview: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments"], + listCommits: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/commits"], + listFiles: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/files"], + listRequestedReviewers: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], + listReviewComments: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/comments"], + listReviewCommentsForRepo: ["GET /repos/{owner}/{repo}/pulls/comments"], + listReviews: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], + merge: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge"], + removeRequestedReviewers: ["DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], + requestReviewers: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], + submitReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events"], + update: ["PATCH /repos/{owner}/{repo}/pulls/{pull_number}"], + updateBranch: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch", { + mediaType: { + previews: ["lydian"] + } + }], + updateReview: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], + updateReviewComment: ["PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}"] + }, + rateLimit: { + get: ["GET /rate_limit"] + }, + reactions: { + createForCommitComment: ["POST /repos/{owner}/{repo}/comments/{comment_id}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + createForIssue: ["POST /repos/{owner}/{repo}/issues/{issue_number}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + createForIssueComment: ["POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + createForPullRequestReviewComment: ["POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + createForTeamDiscussionCommentInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + createForTeamDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + deleteForCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id}", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + deleteForIssue: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id}", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + deleteForIssueComment: ["DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id}", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + deleteForPullRequestComment: ["DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id}", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + deleteForTeamDiscussion: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id}", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + deleteForTeamDiscussionComment: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id}", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + listForCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + listForIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + listForIssueComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + listForPullRequestReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + listForTeamDiscussionCommentInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }], + listForTeamDiscussionInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", { + mediaType: { + previews: ["squirrel-girl"] + } + }] + }, + repos: { + acceptInvitation: ["PATCH /user/repository_invitations/{invitation_id}"], + addAppAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { + mapToData: "apps" + }], + addCollaborator: ["PUT /repos/{owner}/{repo}/collaborators/{username}"], + addStatusCheckContexts: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { + mapToData: "contexts" + }], + addTeamAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { + mapToData: "teams" + }], + addUserAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { + mapToData: "users" + }], + checkCollaborator: ["GET /repos/{owner}/{repo}/collaborators/{username}"], + checkVulnerabilityAlerts: ["GET /repos/{owner}/{repo}/vulnerability-alerts", { + mediaType: { + previews: ["dorian"] + } + }], + compareCommits: ["GET /repos/{owner}/{repo}/compare/{base}...{head}"], + createCommitComment: ["POST /repos/{owner}/{repo}/commits/{commit_sha}/comments"], + createCommitSignatureProtection: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures", { + mediaType: { + previews: ["zzzax"] + } + }], + createCommitStatus: ["POST /repos/{owner}/{repo}/statuses/{sha}"], + createDeployKey: ["POST /repos/{owner}/{repo}/keys"], + createDeployment: ["POST /repos/{owner}/{repo}/deployments"], + createDeploymentStatus: ["POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses"], + createDispatchEvent: ["POST /repos/{owner}/{repo}/dispatches"], + createForAuthenticatedUser: ["POST /user/repos"], + createFork: ["POST /repos/{owner}/{repo}/forks"], + createInOrg: ["POST /orgs/{org}/repos"], + createOrUpdateFileContents: ["PUT /repos/{owner}/{repo}/contents/{path}"], + createPagesSite: ["POST /repos/{owner}/{repo}/pages", { + mediaType: { + previews: ["switcheroo"] + } + }], + createRelease: ["POST /repos/{owner}/{repo}/releases"], + createUsingTemplate: ["POST /repos/{template_owner}/{template_repo}/generate", { + mediaType: { + previews: ["baptiste"] + } + }], + createWebhook: ["POST /repos/{owner}/{repo}/hooks"], + declineInvitation: ["DELETE /user/repository_invitations/{invitation_id}"], + delete: ["DELETE /repos/{owner}/{repo}"], + deleteAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions"], + deleteAdminBranchProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], + deleteBranchProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection"], + deleteCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}"], + deleteCommitSignatureProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures", { + mediaType: { + previews: ["zzzax"] + } + }], + deleteDeployKey: ["DELETE /repos/{owner}/{repo}/keys/{key_id}"], + deleteDeployment: ["DELETE /repos/{owner}/{repo}/deployments/{deployment_id}"], + deleteFile: ["DELETE /repos/{owner}/{repo}/contents/{path}"], + deleteInvitation: ["DELETE /repos/{owner}/{repo}/invitations/{invitation_id}"], + deletePagesSite: ["DELETE /repos/{owner}/{repo}/pages", { + mediaType: { + previews: ["switcheroo"] + } + }], + deletePullRequestReviewProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + deleteRelease: ["DELETE /repos/{owner}/{repo}/releases/{release_id}"], + deleteReleaseAsset: ["DELETE /repos/{owner}/{repo}/releases/assets/{asset_id}"], + deleteWebhook: ["DELETE /repos/{owner}/{repo}/hooks/{hook_id}"], + disableAutomatedSecurityFixes: ["DELETE /repos/{owner}/{repo}/automated-security-fixes", { + mediaType: { + previews: ["london"] + } + }], + disableVulnerabilityAlerts: ["DELETE /repos/{owner}/{repo}/vulnerability-alerts", { + mediaType: { + previews: ["dorian"] + } + }], + downloadArchive: ["GET /repos/{owner}/{repo}/{archive_format}/{ref}"], + enableAutomatedSecurityFixes: ["PUT /repos/{owner}/{repo}/automated-security-fixes", { + mediaType: { + previews: ["london"] + } + }], + enableVulnerabilityAlerts: ["PUT /repos/{owner}/{repo}/vulnerability-alerts", { + mediaType: { + previews: ["dorian"] + } + }], + get: ["GET /repos/{owner}/{repo}"], + getAccessRestrictions: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions"], + getAdminBranchProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], + getAllStatusCheckContexts: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts"], + getAllTopics: ["GET /repos/{owner}/{repo}/topics", { + mediaType: { + previews: ["mercy"] + } + }], + getAppsWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps"], + getBranch: ["GET /repos/{owner}/{repo}/branches/{branch}"], + getBranchProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection"], + getClones: ["GET /repos/{owner}/{repo}/traffic/clones"], + getCodeFrequencyStats: ["GET /repos/{owner}/{repo}/stats/code_frequency"], + getCollaboratorPermissionLevel: ["GET /repos/{owner}/{repo}/collaborators/{username}/permission"], + getCombinedStatusForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/status"], + getCommit: ["GET /repos/{owner}/{repo}/commits/{ref}"], + getCommitActivityStats: ["GET /repos/{owner}/{repo}/stats/commit_activity"], + getCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}"], + getCommitSignatureProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures", { + mediaType: { + previews: ["zzzax"] + } + }], + getCommunityProfileMetrics: ["GET /repos/{owner}/{repo}/community/profile"], + getContent: ["GET /repos/{owner}/{repo}/contents/{path}"], + getContributorsStats: ["GET /repos/{owner}/{repo}/stats/contributors"], + getDeployKey: ["GET /repos/{owner}/{repo}/keys/{key_id}"], + getDeployment: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}"], + getDeploymentStatus: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id}"], + getLatestPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/latest"], + getLatestRelease: ["GET /repos/{owner}/{repo}/releases/latest"], + getPages: ["GET /repos/{owner}/{repo}/pages"], + getPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/{build_id}"], + getParticipationStats: ["GET /repos/{owner}/{repo}/stats/participation"], + getPullRequestReviewProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + getPunchCardStats: ["GET /repos/{owner}/{repo}/stats/punch_card"], + getReadme: ["GET /repos/{owner}/{repo}/readme"], + getRelease: ["GET /repos/{owner}/{repo}/releases/{release_id}"], + getReleaseAsset: ["GET /repos/{owner}/{repo}/releases/assets/{asset_id}"], + getReleaseByTag: ["GET /repos/{owner}/{repo}/releases/tags/{tag}"], + getStatusChecksProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], + getTeamsWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams"], + getTopPaths: ["GET /repos/{owner}/{repo}/traffic/popular/paths"], + getTopReferrers: ["GET /repos/{owner}/{repo}/traffic/popular/referrers"], + getUsersWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users"], + getViews: ["GET /repos/{owner}/{repo}/traffic/views"], + getWebhook: ["GET /repos/{owner}/{repo}/hooks/{hook_id}"], + listBranches: ["GET /repos/{owner}/{repo}/branches"], + listBranchesForHeadCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head", { + mediaType: { + previews: ["groot"] + } + }], + listCollaborators: ["GET /repos/{owner}/{repo}/collaborators"], + listCommentsForCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/comments"], + listCommitCommentsForRepo: ["GET /repos/{owner}/{repo}/comments"], + listCommitStatusesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/statuses"], + listCommits: ["GET /repos/{owner}/{repo}/commits"], + listContributors: ["GET /repos/{owner}/{repo}/contributors"], + listDeployKeys: ["GET /repos/{owner}/{repo}/keys"], + listDeploymentStatuses: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses"], + listDeployments: ["GET /repos/{owner}/{repo}/deployments"], + listForAuthenticatedUser: ["GET /user/repos"], + listForOrg: ["GET /orgs/{org}/repos"], + listForUser: ["GET /users/{username}/repos"], + listForks: ["GET /repos/{owner}/{repo}/forks"], + listInvitations: ["GET /repos/{owner}/{repo}/invitations"], + listInvitationsForAuthenticatedUser: ["GET /user/repository_invitations"], + listLanguages: ["GET /repos/{owner}/{repo}/languages"], + listPagesBuilds: ["GET /repos/{owner}/{repo}/pages/builds"], + listPublic: ["GET /repositories"], + listPullRequestsAssociatedWithCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls", { + mediaType: { + previews: ["groot"] + } + }], + listReleaseAssets: ["GET /repos/{owner}/{repo}/releases/{release_id}/assets"], + listReleases: ["GET /repos/{owner}/{repo}/releases"], + listTags: ["GET /repos/{owner}/{repo}/tags"], + listTeams: ["GET /repos/{owner}/{repo}/teams"], + listWebhooks: ["GET /repos/{owner}/{repo}/hooks"], + merge: ["POST /repos/{owner}/{repo}/merges"], + pingWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/pings"], + removeAppAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { + mapToData: "apps" + }], + removeCollaborator: ["DELETE /repos/{owner}/{repo}/collaborators/{username}"], + removeStatusCheckContexts: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { + mapToData: "contexts" + }], + removeStatusCheckProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], + removeTeamAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { + mapToData: "teams" + }], + removeUserAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { + mapToData: "users" + }], + replaceAllTopics: ["PUT /repos/{owner}/{repo}/topics", { + mediaType: { + previews: ["mercy"] + } + }], + requestPagesBuild: ["POST /repos/{owner}/{repo}/pages/builds"], + setAdminBranchProtection: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], + setAppAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { + mapToData: "apps" + }], + setStatusCheckContexts: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { + mapToData: "contexts" + }], + setTeamAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { + mapToData: "teams" + }], + setUserAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { + mapToData: "users" + }], + testPushWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/tests"], + transfer: ["POST /repos/{owner}/{repo}/transfer"], + update: ["PATCH /repos/{owner}/{repo}"], + updateBranchProtection: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection"], + updateCommitComment: ["PATCH /repos/{owner}/{repo}/comments/{comment_id}"], + updateInformationAboutPagesSite: ["PUT /repos/{owner}/{repo}/pages"], + updateInvitation: ["PATCH /repos/{owner}/{repo}/invitations/{invitation_id}"], + updatePullRequestReviewProtection: ["PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + updateRelease: ["PATCH /repos/{owner}/{repo}/releases/{release_id}"], + updateReleaseAsset: ["PATCH /repos/{owner}/{repo}/releases/assets/{asset_id}"], + updateStatusCheckPotection: ["PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], + updateWebhook: ["PATCH /repos/{owner}/{repo}/hooks/{hook_id}"], + uploadReleaseAsset: ["POST /repos/{owner}/{repo}/releases/{release_id}/assets{?name,label}", { + baseUrl: "https://uploads.github.com" + }] + }, + search: { + code: ["GET /search/code"], + commits: ["GET /search/commits", { + mediaType: { + previews: ["cloak"] + } + }], + issuesAndPullRequests: ["GET /search/issues"], + labels: ["GET /search/labels"], + repos: ["GET /search/repositories"], + topics: ["GET /search/topics"], + users: ["GET /search/users"] + }, + teams: { + addOrUpdateMembershipForUserInOrg: ["PUT /orgs/{org}/teams/{team_slug}/memberships/{username}"], + addOrUpdateProjectPermissionsInOrg: ["PUT /orgs/{org}/teams/{team_slug}/projects/{project_id}", { + mediaType: { + previews: ["inertia"] + } + }], + addOrUpdateRepoPermissionsInOrg: ["PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], + checkPermissionsForProjectInOrg: ["GET /orgs/{org}/teams/{team_slug}/projects/{project_id}", { + mediaType: { + previews: ["inertia"] + } + }], + checkPermissionsForRepoInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], + create: ["POST /orgs/{org}/teams"], + createDiscussionCommentInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments"], + createDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions"], + deleteDiscussionCommentInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], + deleteDiscussionInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], + deleteInOrg: ["DELETE /orgs/{org}/teams/{team_slug}"], + getByName: ["GET /orgs/{org}/teams/{team_slug}"], + getDiscussionCommentInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], + getDiscussionInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], + getMembershipForUserInOrg: ["GET /orgs/{org}/teams/{team_slug}/memberships/{username}"], + list: ["GET /orgs/{org}/teams"], + listChildInOrg: ["GET /orgs/{org}/teams/{team_slug}/teams"], + listDiscussionCommentsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments"], + listDiscussionsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions"], + listForAuthenticatedUser: ["GET /user/teams"], + listMembersInOrg: ["GET /orgs/{org}/teams/{team_slug}/members"], + listPendingInvitationsInOrg: ["GET /orgs/{org}/teams/{team_slug}/invitations"], + listProjectsInOrg: ["GET /orgs/{org}/teams/{team_slug}/projects", { + mediaType: { + previews: ["inertia"] + } + }], + listReposInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos"], + removeMembershipForUserInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}"], + removeProjectInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id}"], + removeRepoInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], + updateDiscussionCommentInOrg: ["PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], + updateDiscussionInOrg: ["PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], + updateInOrg: ["PATCH /orgs/{org}/teams/{team_slug}"] + }, + users: { + addEmailForAuthenticated: ["POST /user/emails"], + block: ["PUT /user/blocks/{username}"], + checkBlocked: ["GET /user/blocks/{username}"], + checkFollowingForUser: ["GET /users/{username}/following/{target_user}"], + checkPersonIsFollowedByAuthenticated: ["GET /user/following/{username}"], + createGpgKeyForAuthenticated: ["POST /user/gpg_keys"], + createPublicSshKeyForAuthenticated: ["POST /user/keys"], + deleteEmailForAuthenticated: ["DELETE /user/emails"], + deleteGpgKeyForAuthenticated: ["DELETE /user/gpg_keys/{gpg_key_id}"], + deletePublicSshKeyForAuthenticated: ["DELETE /user/keys/{key_id}"], + follow: ["PUT /user/following/{username}"], + getAuthenticated: ["GET /user"], + getByUsername: ["GET /users/{username}"], + getContextForUser: ["GET /users/{username}/hovercard"], + getGpgKeyForAuthenticated: ["GET /user/gpg_keys/{gpg_key_id}"], + getPublicSshKeyForAuthenticated: ["GET /user/keys/{key_id}"], + list: ["GET /users"], + listBlockedByAuthenticated: ["GET /user/blocks"], + listEmailsForAuthenticated: ["GET /user/emails"], + listFollowedByAuthenticated: ["GET /user/following"], + listFollowersForAuthenticatedUser: ["GET /user/followers"], + listFollowersForUser: ["GET /users/{username}/followers"], + listFollowingForUser: ["GET /users/{username}/following"], + listGpgKeysForAuthenticated: ["GET /user/gpg_keys"], + listGpgKeysForUser: ["GET /users/{username}/gpg_keys"], + listPublicEmailsForAuthenticated: ["GET /user/public_emails"], + listPublicKeysForUser: ["GET /users/{username}/keys"], + listPublicSshKeysForAuthenticated: ["GET /user/keys"], + setPrimaryEmailVisibilityForAuthenticated: ["PATCH /user/email/visibility"], + unblock: ["DELETE /user/blocks/{username}"], + unfollow: ["DELETE /user/following/{username}"], + updateAuthenticated: ["PATCH /user"] + } +}; + +const VERSION = "4.0.0"; + +function endpointsToMethods(octokit, endpointsMap) { + const newMethods = {}; + + for (const [scope, endpoints] of Object.entries(endpointsMap)) { + for (const [methodName, endpoint] of Object.entries(endpoints)) { + const [route, defaults, decorations] = endpoint; + const [method, url] = route.split(/ /); + const endpointDefaults = Object.assign({ + method, + url + }, defaults); + + if (!newMethods[scope]) { + newMethods[scope] = {}; + } + + const scopeMethods = newMethods[scope]; + + if (decorations) { + scopeMethods[methodName] = decorate(octokit, scope, methodName, endpointDefaults, decorations); + continue; + } + + scopeMethods[methodName] = octokit.request.defaults(endpointDefaults); + } + } + + return newMethods; +} + +function decorate(octokit, scope, methodName, defaults, decorations) { + const requestWithDefaults = octokit.request.defaults(defaults); + /* istanbul ignore next */ + + function withDecorations(...args) { + // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 + let options = requestWithDefaults.endpoint.merge(...args); // There are currently no other decorations than `.mapToData` + + if (decorations.mapToData) { + options = Object.assign({}, options, { + data: options[decorations.mapToData], + [decorations.mapToData]: undefined + }); + return requestWithDefaults(options); + } + + if (decorations.renamed) { + const [newScope, newMethodName] = decorations.renamed; + octokit.log.warn(`octokit.${scope}.${methodName}() has been renamed to octokit.${newScope}.${newMethodName}()`); + } + + if (decorations.deprecated) { + octokit.log.warn(decorations.deprecated); + } + + if (decorations.renamedParameters) { + // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 + const options = requestWithDefaults.endpoint.merge(...args); + + for (const [name, alias] of Object.entries(decorations.renamedParameters)) { + if (name in options) { + octokit.log.warn(`"${name}" parameter is deprecated for "octokit.${scope}.${methodName}()". Use "${alias}" instead`); + + if (!(alias in options)) { + options[alias] = options[name]; + } + + delete options[name]; + } + } + + return requestWithDefaults(options); + } // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 + + + return requestWithDefaults(...args); + } + + return Object.assign(withDecorations, requestWithDefaults); +} + +/** + * This plugin is a 1:1 copy of internal @octokit/rest plugins. The primary + * goal is to rebuild @octokit/rest on top of @octokit/core. Once that is + * done, we will remove the registerEndpoints methods and return the methods + * directly as with the other plugins. At that point we will also remove the + * legacy workarounds and deprecations. + * + * See the plan at + * https://github.com/octokit/plugin-rest-endpoint-methods.js/pull/1 + */ + +function restEndpointMethods(octokit) { + return endpointsToMethods(octokit, Endpoints); +} +restEndpointMethods.VERSION = VERSION; + +exports.restEndpointMethods = restEndpointMethods; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 844: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = rng; + +var _crypto = _interopRequireDefault(__webpack_require__(417)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8 = new Uint8Array(16); + +function rng() { + return _crypto.default.randomFillSync(rnds8); +} + +/***/ }), + +/***/ 866: +/***/ (function(module) { + +module.exports = removeHook + +function removeHook (state, name, method) { + if (!state.registry[name]) { + return + } + + var index = state.registry[name] + .map(function (registered) { return registered.orig }) + .indexOf(method) + + if (index === -1) { + return + } + + state.registry[name].splice(index, 1) +} + + +/***/ }), + +/***/ 884: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + + +const path = __webpack_require__(622); +const niceTry = __webpack_require__(948); +const resolveCommand = __webpack_require__(542); +const escape = __webpack_require__(759); +const readShebang = __webpack_require__(306); +const semver = __webpack_require__(607); + +const isWin = process.platform === 'win32'; +const isExecutableRegExp = /\.(?:com|exe)$/i; +const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i; + +// `options.shell` is supported in Node ^4.8.0, ^5.7.0 and >= 6.0.0 +const supportsShellOption = niceTry(() => semver.satisfies(process.version, '^4.8.0 || ^5.7.0 || >= 6.0.0', true)) || false; + +function detectShebang(parsed) { + parsed.file = resolveCommand(parsed); + + const shebang = parsed.file && readShebang(parsed.file); + + if (shebang) { + parsed.args.unshift(parsed.file); + parsed.command = shebang; + + return resolveCommand(parsed); + } + + return parsed.file; +} + +function parseNonShell(parsed) { + if (!isWin) { + return parsed; + } + + // Detect & add support for shebangs + const commandFile = detectShebang(parsed); + + // We don't need a shell if the command filename is an executable + const needsShell = !isExecutableRegExp.test(commandFile); + + // If a shell is required, use cmd.exe and take care of escaping everything correctly + // Note that `forceShell` is an hidden option used only in tests + if (parsed.options.forceShell || needsShell) { + // Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/` + // The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument + // Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called, + // we need to double escape them + const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile); + + // Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar) + // This is necessary otherwise it will always fail with ENOENT in those cases + parsed.command = path.normalize(parsed.command); + + // Escape command & arguments + parsed.command = escape.command(parsed.command); + parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars)); + + const shellCommand = [parsed.command].concat(parsed.args).join(' '); + + parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; + parsed.command = process.env.comspec || 'cmd.exe'; + parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped + } + + return parsed; +} + +function parseShell(parsed) { + // If node supports the shell option, there's no need to mimic its behavior + if (supportsShellOption) { + return parsed; + } + + // Mimic node shell option + // See https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335 + const shellCommand = [parsed.command].concat(parsed.args).join(' '); + + if (isWin) { + parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe'; + parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`]; + parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped + } else { + if (typeof parsed.options.shell === 'string') { + parsed.command = parsed.options.shell; + } else if (process.platform === 'android') { + parsed.command = '/system/bin/sh'; + } else { + parsed.command = '/bin/sh'; + } + + parsed.args = ['-c', shellCommand]; + } + + return parsed; +} + +function parse(command, args, options) { + // Normalize arguments, similar to nodejs + if (args && !Array.isArray(args)) { + options = args; + args = null; + } + + args = args ? args.slice(0) : []; // Clone array to avoid changing the original + options = Object.assign({}, options); // Clone object to avoid changing the original + + // Build our parsed object + const parsed = { + command, + args, + options, + file: undefined, + original: { + command, + args, + }, + }; + + // Delegate further parsing to shell or non-shell + return options.shell ? parseShell(parsed) : parseNonShell(parsed); +} + +module.exports = parse; + + +/***/ }), + +/***/ 893: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _rng = _interopRequireDefault(__webpack_require__(844)); + +var _bytesToUuid = _interopRequireDefault(__webpack_require__(390)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _bytesToUuid.default)(b); +} + +var _default = v1; +exports.default = _default; + +/***/ }), + +/***/ 898: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, '__esModule', { value: true }); + +var request = __webpack_require__(753); +var universalUserAgent = __webpack_require__(796); + +const VERSION = "4.5.1"; + +class GraphqlError extends Error { + constructor(request, response) { + const message = response.data.errors[0].message; + super(message); + Object.assign(this, response.data); + this.name = "GraphqlError"; + this.request = request; // Maintains proper stack trace (only available on V8) + + /* istanbul ignore next */ + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } + +} + +const NON_VARIABLE_OPTIONS = ["method", "baseUrl", "url", "headers", "request", "query", "mediaType"]; +function graphql(request, query, options) { + options = typeof query === "string" ? options = Object.assign({ + query + }, options) : options = query; + const requestOptions = Object.keys(options).reduce((result, key) => { + if (NON_VARIABLE_OPTIONS.includes(key)) { + result[key] = options[key]; + return result; + } + + if (!result.variables) { + result.variables = {}; + } + + result.variables[key] = options[key]; + return result; + }, {}); + return request(requestOptions).then(response => { + if (response.data.errors) { + throw new GraphqlError(requestOptions, { + data: response.data + }); + } + + return response.data.data; + }); +} + +function withDefaults(request$1, newDefaults) { + const newRequest = request$1.defaults(newDefaults); + + const newApi = (query, options) => { + return graphql(newRequest, query, options); + }; + + return Object.assign(newApi, { + defaults: withDefaults.bind(null, newRequest), + endpoint: request.request.endpoint + }); +} + +const graphql$1 = withDefaults(request.request, { + headers: { + "user-agent": `octokit-graphql.js/${VERSION} ${universalUserAgent.getUserAgent()}` + }, + method: "POST", + url: "/graphql" +}); +function withCustomRequest(customRequest) { + return withDefaults(customRequest, { + method: "POST", + url: "/graphql" + }); +} + +exports.graphql = graphql$1; +exports.withCustomRequest = withCustomRequest; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 907: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +var shebangRegex = __webpack_require__(473); + +module.exports = function (str) { + var match = str.match(shebangRegex); + + if (!match) { + return null; + } + + var arr = match[0].replace(/#! ?/, '').split(' '); + var bin = arr[0].split('/').pop(); + var arg = arr[1]; + + return (bin === 'env' ? + arg : + bin + (arg ? ' ' + arg : '') + ); +}; + + +/***/ }), + +/***/ 921: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -const url = __webpack_require__(835); -function getProxyUrl(reqUrl) { - let usingSsl = reqUrl.protocol === 'https:'; - let proxyUrl; - if (checkBypass(reqUrl)) { - return proxyUrl; - } - let proxyVar; - if (usingSsl) { - proxyVar = process.env['https_proxy'] || process.env['HTTPS_PROXY']; - } - else { - proxyVar = process.env['http_proxy'] || process.env['HTTP_PROXY']; - } - if (proxyVar) { - proxyUrl = url.parse(proxyVar); - } - return proxyUrl; -} -exports.getProxyUrl = getProxyUrl; -function checkBypass(reqUrl) { - if (!reqUrl.hostname) { - return false; - } - let noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; - if (!noProxy) { - return false; - } - // Determine the request port - let reqPort; - if (reqUrl.port) { - reqPort = Number(reqUrl.port); - } - else if (reqUrl.protocol === 'http:') { - reqPort = 80; - } - else if (reqUrl.protocol === 'https:') { - reqPort = 443; - } - // Format the request hostname and hostname with port - let upperReqHosts = [reqUrl.hostname.toUpperCase()]; - if (typeof reqPort === 'number') { - upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); - } - // Compare request host against noproxy - for (let upperNoProxyItem of noProxy - .split(',') - .map(x => x.trim().toUpperCase()) - .filter(x => x)) { - if (upperReqHosts.some(x => x === upperNoProxyItem)) { - return true; - } - } - return false; -} -exports.checkBypass = checkBypass; +exports.Octokit = void 0; +const core_1 = __webpack_require__(448); +const plugin_paginate_rest_1 = __webpack_require__(299); +const plugin_rest_endpoint_methods_1 = __webpack_require__(842); +exports.Octokit = core_1.Octokit.plugin(plugin_paginate_rest_1.paginateRest, plugin_rest_endpoint_methods_1.restEndpointMethods); /***/ }), -/***/ 953: +/***/ 940: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; @@ -5025,58 +10471,6 @@ var __importStar = (this && this.__importStar) || function (mod) { __setModuleDefault(result, mod); return result; }; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.setupPython = void 0; -const core = __importStar(__webpack_require__(470)); -const tc = __importStar(__webpack_require__(533)); -const path = __importStar(__webpack_require__(622)); -const semver = __importStar(__webpack_require__(280)); -/** - * Setup for Python from the GitHub Actions tool cache - * Converted from https://github.com/actions/setup-python - * - * @param {string} versionSpec version of Python - * @param {string} arch architecture (x64|x32) - */ -function setupPython(versionSpec, arch) { - return new Promise(resolve => { - const IS_WINDOWS = process.platform === 'win32'; - // Find the version of Python we want in the tool cache - const installDir = tc.find('Python', versionSpec, arch); - core.debug(`installDir: ${installDir}`); - // Set paths - core.exportVariable('pythonLocation', installDir); - core.addPath(installDir); - if (IS_WINDOWS) { - core.addPath(path.join(installDir, 'Scripts')); - } - else { - core.addPath(path.join(installDir, 'bin')); - } - if (IS_WINDOWS) { - // Add --user directory - // `installDir` from tool cache should look like $AGENT_TOOLSDIRECTORY/Python//x64/ - // So if `findLocalTool` succeeded above, we must have a conformant `installDir` - const version = path.basename(path.dirname(installDir)); - const major = semver.major(version); - const minor = semver.minor(version); - const userScriptsDir = path.join(process.env['APPDATA'] || '', 'Python', `Python${major}${minor}`, 'Scripts'); - core.addPath(userScriptsDir); - } - // On Linux and macOS, pip will create the --user directory and add it to PATH as needed. - resolve(); - }); -} -exports.setupPython = setupPython; - - -/***/ }), - -/***/ 979: -/***/ (function(__unusedmodule, exports, __webpack_require__) { - -"use strict"; - var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { @@ -5086,66 +10480,666 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; Object.defineProperty(exports, "__esModule", { value: true }); +exports.createPullRequest = void 0; const core = __importStar(__webpack_require__(470)); -/** - * Internal class for retries - */ -class RetryHelper { - constructor(maxAttempts, minSeconds, maxSeconds) { - if (maxAttempts < 1) { - throw new Error('max attempts should be greater than or equal to 1'); - } - this.maxAttempts = maxAttempts; - this.minSeconds = Math.floor(minSeconds); - this.maxSeconds = Math.floor(maxSeconds); - if (this.minSeconds > this.maxSeconds) { - throw new Error('min seconds should be less than or equal to max seconds'); - } - } - execute(action, isRetryable) { - return __awaiter(this, void 0, void 0, function* () { - let attempt = 1; - while (attempt < this.maxAttempts) { - // Try - try { - return yield action(); - } - catch (err) { - if (isRetryable && !isRetryable(err)) { - throw err; - } - core.info(err.message); - } - // Sleep - const seconds = this.getSleepAmount(); - core.info(`Waiting ${seconds} seconds before trying again`); - yield this.sleep(seconds); - attempt++; +const create_or_update_branch_1 = __webpack_require__(159); +const github_helper_1 = __webpack_require__(718); +const git_command_manager_1 = __webpack_require__(289); +const git_config_helper_1 = __webpack_require__(468); +const git_identity_helper_1 = __webpack_require__(723); +const utils = __importStar(__webpack_require__(611)); +const EXTRAHEADER_OPTION = 'http.https://github.com/.extraheader'; +const EXTRAHEADER_VALUE_REGEX = '^AUTHORIZATION:'; +const DEFAULT_COMMIT_MESSAGE = '[create-pull-request] automated change'; +const DEFAULT_TITLE = 'Changes by create-pull-request action'; +const DEFAULT_BODY = 'Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action'; +const DEFAULT_BRANCH = 'create-pull-request/patch'; +function createPullRequest(inputs) { + return __awaiter(this, void 0, void 0, function* () { + let gitConfigHelper; + let extraHeaderOption = new git_config_helper_1.ConfigOption(); + try { + // Get the repository path + const repoPath = utils.getRepoPath(inputs.path); + // Create a git command manager + const git = yield git_command_manager_1.GitCommandManager.create(repoPath); + // Unset and save the extraheader config option if it exists + gitConfigHelper = new git_config_helper_1.GitConfigHelper(git); + extraHeaderOption = yield gitConfigHelper.getAndUnsetConfigOption(EXTRAHEADER_OPTION, EXTRAHEADER_VALUE_REGEX); + //github_token = inputs.token + //path = repoPath + // Set defaults + inputs.commitMessage = inputs.commitMessage + ? inputs.commitMessage + : DEFAULT_COMMIT_MESSAGE; + inputs.title = inputs.title ? inputs.title : DEFAULT_TITLE; + inputs.body = inputs.body ? inputs.body : DEFAULT_BODY; + inputs.branch = inputs.branch ? inputs.branch : DEFAULT_BRANCH; + // Determine the GitHub repository from git config + // This will be the target repository for the pull request branch + const remoteOriginUrlConfig = yield gitConfigHelper.getConfigOption('remote.origin.url'); + const remote = yield utils.getRemoteDetail(remoteOriginUrlConfig.value); + core.info(`Pull request branch target repository set to ${remote.repository}`); + if (remote.protocol == 'HTTPS') { + core.debug('Using HTTPS protocol'); + // Encode and configure the basic credential for HTTPS access + const basicCredential = Buffer.from(`x-access-token:${inputs.token}`, 'utf8').toString('base64'); + core.setSecret(basicCredential); + git.setAuthGitOptions([ + '-c', + `http.https://github.com/.extraheader=AUTHORIZATION: basic ${basicCredential}` + ]); } - // Last attempt - return yield action(); - }); - } - getSleepAmount() { - return (Math.floor(Math.random() * (this.maxSeconds - this.minSeconds + 1)) + - this.minSeconds); - } - sleep(seconds) { - return __awaiter(this, void 0, void 0, function* () { - return new Promise(resolve => setTimeout(resolve, seconds * 1000)); - }); - } + // Determine if the checked out ref is a valid base for a pull request + // The action needs the checked out HEAD ref to be a branch + // This check will fail in the following cases: + // - HEAD is detached + // - HEAD is a merge commit (pull_request events) + // - HEAD is a tag + const symbolicRefResult = yield git.exec(['symbolic-ref', 'HEAD', '--short'], true); + if (symbolicRefResult.exitCode != 0) { + core.debug(`${symbolicRefResult.stderr}`); + throw new Error('The checked out ref is not a valid base for a pull request. Unable to continue.'); + } + const workingBase = symbolicRefResult.stdout.trim(); + // Exit if the working base is a PR branch created by this action. + // This may occur when using a PAT instead of GITHUB_TOKEN because + // a PAT allows workflow actions to trigger further events. + if (workingBase.startsWith(inputs.branch)) { + throw new Error(`Working base branch '${workingBase}' was created by this action. Unable to continue.`); + } + // Apply the branch suffix if set + if (inputs.branchSuffix) { + switch (inputs.branchSuffix) { + case 'short-commit-hash': + // Suffix with the short SHA1 hash + inputs.branch = `${inputs.branch}-${yield git.revParse('HEAD', [ + '--short' + ])}`; + break; + case 'timestamp': + // Suffix with the current timestamp + inputs.branch = `${inputs.branch}-${utils.secondsSinceEpoch()}`; + break; + case 'random': + // Suffix with a 7 character random string + inputs.branch = `${inputs.branch}-${utils.randomString()}`; + break; + default: + throw new Error(`Branch suffix '${inputs.branchSuffix}' is not a valid value. Unable to continue.`); + } + } + // Output head branch + core.info(`Pull request branch to create or update set to '${inputs.branch}'`); + // Determine the committer and author + const gitIdentityHelper = new git_identity_helper_1.GitIdentityHelper(git); + const identity = yield gitIdentityHelper.getIdentity(inputs.author, inputs.committer); + git.setIdentityGitOptions([ + '-c', + `author.name=${identity.authorName}`, + '-c', + `author.email=${identity.authorEmail}`, + '-c', + `committer.name=${identity.committerName}`, + '-c', + `committer.email=${identity.committerEmail}` + ]); + core.info(`Configured git committer as '${identity.committerName} <${identity.committerEmail}>'`); + core.info(`Configured git author as '${identity.authorName} <${identity.authorEmail}>'`); + // Create or update the pull request branch + const result = yield create_or_update_branch_1.createOrUpdateBranch(git, inputs.commitMessage, inputs.base, inputs.branch); + if (['created', 'updated'].includes(result.action)) { + // The branch was created or updated + core.info(`Pushing pull request branch to 'origin/${inputs.branch}'`); + yield git.push(['--force', 'origin', `HEAD:refs/heads/${inputs.branch}`]); + // Set the base. It would have been '' if not specified as an input + inputs.base = result.base; + if (result.hasDiffWithBase) { + // Create or update the pull request + const githubHelper = new github_helper_1.GitHubHelper(inputs.token); + yield githubHelper.createOrUpdatePullRequest(inputs, remote.repository); + // coupr.create_or_update_pull_request( + // github_token, + // github_repository, + // branch, + // base, + // title, + // body, + // os.environ.get("CPR_LABELS"), + // os.environ.get("CPR_ASSIGNEES"), + // os.environ.get("CPR_MILESTONE"), + // os.environ.get("CPR_REVIEWERS"), + // os.environ.get("CPR_TEAM_REVIEWERS"), + // os.environ.get("CPR_PROJECT_NAME"), + // os.environ.get("CPR_PROJECT_COLUMN_NAME"), + // os.environ.get("CPR_DRAFT"), + // os.environ.get("CPR_REQUEST_TO_PARENT"), + // ) + } + else { + // If there is no longer a diff with the base delete the branch + core.info(`Branch '${inputs.branch}' no longer differs from base branch '${inputs.base}'`); + core.info(`Closing pull request and deleting branch '${inputs.branch}'`); + yield git.push([ + '--delete', + '--force', + 'origin', + `refs/heads/${inputs.branch}` + ]); + } + } + } + catch (error) { + core.setFailed(error.message); + } + finally { + // Restore the extraheader config option + if (extraHeaderOption.value != '') { + if (yield gitConfigHelper.addConfigOption(EXTRAHEADER_OPTION, extraHeaderOption.value)) + core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`); + } + } + }); } -exports.RetryHelper = RetryHelper; -//# sourceMappingURL=retry-helper.js.map +exports.createPullRequest = createPullRequest; + + +/***/ }), + +/***/ 948: +/***/ (function(module) { + +"use strict"; + + +/** + * Tries to execute a function and discards any error that occurs. + * @param {Function} fn - Function that might or might not throw an error. + * @returns {?*} Return-value of the function when no error occurred. + */ +module.exports = function(fn) { + + try { return fn() } catch (e) {} + +} + +/***/ }), + +/***/ 955: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const path = __webpack_require__(622); +const childProcess = __webpack_require__(129); +const crossSpawn = __webpack_require__(774); +const stripEof = __webpack_require__(768); +const npmRunPath = __webpack_require__(621); +const isStream = __webpack_require__(323); +const _getStream = __webpack_require__(145); +const pFinally = __webpack_require__(697); +const onExit = __webpack_require__(260); +const errname = __webpack_require__(427); +const stdio = __webpack_require__(168); + +const TEN_MEGABYTES = 1000 * 1000 * 10; + +function handleArgs(cmd, args, opts) { + let parsed; + + opts = Object.assign({ + extendEnv: true, + env: {} + }, opts); + + if (opts.extendEnv) { + opts.env = Object.assign({}, process.env, opts.env); + } + + if (opts.__winShell === true) { + delete opts.__winShell; + parsed = { + command: cmd, + args, + options: opts, + file: cmd, + original: { + cmd, + args + } + }; + } else { + parsed = crossSpawn._parse(cmd, args, opts); + } + + opts = Object.assign({ + maxBuffer: TEN_MEGABYTES, + buffer: true, + stripEof: true, + preferLocal: true, + localDir: parsed.options.cwd || process.cwd(), + encoding: 'utf8', + reject: true, + cleanup: true + }, parsed.options); + + opts.stdio = stdio(opts); + + if (opts.preferLocal) { + opts.env = npmRunPath.env(Object.assign({}, opts, {cwd: opts.localDir})); + } + + if (opts.detached) { + // #115 + opts.cleanup = false; + } + + if (process.platform === 'win32' && path.basename(parsed.command) === 'cmd.exe') { + // #116 + parsed.args.unshift('/q'); + } + + return { + cmd: parsed.command, + args: parsed.args, + opts, + parsed + }; +} + +function handleInput(spawned, input) { + if (input === null || input === undefined) { + return; + } + + if (isStream(input)) { + input.pipe(spawned.stdin); + } else { + spawned.stdin.end(input); + } +} + +function handleOutput(opts, val) { + if (val && opts.stripEof) { + val = stripEof(val); + } + + return val; +} + +function handleShell(fn, cmd, opts) { + let file = '/bin/sh'; + let args = ['-c', cmd]; + + opts = Object.assign({}, opts); + + if (process.platform === 'win32') { + opts.__winShell = true; + file = process.env.comspec || 'cmd.exe'; + args = ['/s', '/c', `"${cmd}"`]; + opts.windowsVerbatimArguments = true; + } + + if (opts.shell) { + file = opts.shell; + delete opts.shell; + } + + return fn(file, args, opts); +} + +function getStream(process, stream, {encoding, buffer, maxBuffer}) { + if (!process[stream]) { + return null; + } + + let ret; + + if (!buffer) { + // TODO: Use `ret = util.promisify(stream.finished)(process[stream]);` when targeting Node.js 10 + ret = new Promise((resolve, reject) => { + process[stream] + .once('end', resolve) + .once('error', reject); + }); + } else if (encoding) { + ret = _getStream(process[stream], { + encoding, + maxBuffer + }); + } else { + ret = _getStream.buffer(process[stream], {maxBuffer}); + } + + return ret.catch(err => { + err.stream = stream; + err.message = `${stream} ${err.message}`; + throw err; + }); +} + +function makeError(result, options) { + const {stdout, stderr} = result; + + let err = result.error; + const {code, signal} = result; + + const {parsed, joinedCmd} = options; + const timedOut = options.timedOut || false; + + if (!err) { + let output = ''; + + if (Array.isArray(parsed.opts.stdio)) { + if (parsed.opts.stdio[2] !== 'inherit') { + output += output.length > 0 ? stderr : `\n${stderr}`; + } + + if (parsed.opts.stdio[1] !== 'inherit') { + output += `\n${stdout}`; + } + } else if (parsed.opts.stdio !== 'inherit') { + output = `\n${stderr}${stdout}`; + } + + err = new Error(`Command failed: ${joinedCmd}${output}`); + err.code = code < 0 ? errname(code) : code; + } + + err.stdout = stdout; + err.stderr = stderr; + err.failed = true; + err.signal = signal || null; + err.cmd = joinedCmd; + err.timedOut = timedOut; + + return err; +} + +function joinCmd(cmd, args) { + let joinedCmd = cmd; + + if (Array.isArray(args) && args.length > 0) { + joinedCmd += ' ' + args.join(' '); + } + + return joinedCmd; +} + +module.exports = (cmd, args, opts) => { + const parsed = handleArgs(cmd, args, opts); + const {encoding, buffer, maxBuffer} = parsed.opts; + const joinedCmd = joinCmd(cmd, args); + + let spawned; + try { + spawned = childProcess.spawn(parsed.cmd, parsed.args, parsed.opts); + } catch (err) { + return Promise.reject(err); + } + + let removeExitHandler; + if (parsed.opts.cleanup) { + removeExitHandler = onExit(() => { + spawned.kill(); + }); + } + + let timeoutId = null; + let timedOut = false; + + const cleanup = () => { + if (timeoutId) { + clearTimeout(timeoutId); + timeoutId = null; + } + + if (removeExitHandler) { + removeExitHandler(); + } + }; + + if (parsed.opts.timeout > 0) { + timeoutId = setTimeout(() => { + timeoutId = null; + timedOut = true; + spawned.kill(parsed.opts.killSignal); + }, parsed.opts.timeout); + } + + const processDone = new Promise(resolve => { + spawned.on('exit', (code, signal) => { + cleanup(); + resolve({code, signal}); + }); + + spawned.on('error', err => { + cleanup(); + resolve({error: err}); + }); + + if (spawned.stdin) { + spawned.stdin.on('error', err => { + cleanup(); + resolve({error: err}); + }); + } + }); + + function destroy() { + if (spawned.stdout) { + spawned.stdout.destroy(); + } + + if (spawned.stderr) { + spawned.stderr.destroy(); + } + } + + const handlePromise = () => pFinally(Promise.all([ + processDone, + getStream(spawned, 'stdout', {encoding, buffer, maxBuffer}), + getStream(spawned, 'stderr', {encoding, buffer, maxBuffer}) + ]).then(arr => { + const result = arr[0]; + result.stdout = arr[1]; + result.stderr = arr[2]; + + if (result.error || result.code !== 0 || result.signal !== null) { + const err = makeError(result, { + joinedCmd, + parsed, + timedOut + }); + + // TODO: missing some timeout logic for killed + // https://github.com/nodejs/node/blob/master/lib/child_process.js#L203 + // err.killed = spawned.killed || killed; + err.killed = err.killed || spawned.killed; + + if (!parsed.opts.reject) { + return err; + } + + throw err; + } + + return { + stdout: handleOutput(parsed.opts, result.stdout), + stderr: handleOutput(parsed.opts, result.stderr), + code: 0, + failed: false, + killed: false, + signal: null, + cmd: joinedCmd, + timedOut: false + }; + }), destroy); + + crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed); + + handleInput(spawned, parsed.opts.input); + + spawned.then = (onfulfilled, onrejected) => handlePromise().then(onfulfilled, onrejected); + spawned.catch = onrejected => handlePromise().catch(onrejected); + + return spawned; +}; + +// TODO: set `stderr: 'ignore'` when that option is implemented +module.exports.stdout = (...args) => module.exports(...args).then(x => x.stdout); + +// TODO: set `stdout: 'ignore'` when that option is implemented +module.exports.stderr = (...args) => module.exports(...args).then(x => x.stderr); + +module.exports.shell = (cmd, opts) => handleShell(module.exports, cmd, opts); + +module.exports.sync = (cmd, args, opts) => { + const parsed = handleArgs(cmd, args, opts); + const joinedCmd = joinCmd(cmd, args); + + if (isStream(parsed.opts.input)) { + throw new TypeError('The `input` option cannot be a stream in sync mode'); + } + + const result = childProcess.spawnSync(parsed.cmd, parsed.args, parsed.opts); + result.code = result.status; + + if (result.error || result.status !== 0 || result.signal !== null) { + const err = makeError(result, { + joinedCmd, + parsed + }); + + if (!parsed.opts.reject) { + return err; + } + + throw err; + } + + return { + stdout: handleOutput(parsed.opts, result.stdout), + stderr: handleOutput(parsed.opts, result.stderr), + code: 0, + failed: false, + signal: null, + cmd: joinedCmd, + timedOut: false + }; +}; + +module.exports.shellSync = (cmd, opts) => handleShell(module.exports.sync, cmd, opts); + + +/***/ }), + +/***/ 966: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const {PassThrough} = __webpack_require__(413); + +module.exports = options => { + options = Object.assign({}, options); + + const {array} = options; + let {encoding} = options; + const buffer = encoding === 'buffer'; + let objectMode = false; + + if (array) { + objectMode = !(encoding || buffer); + } else { + encoding = encoding || 'utf8'; + } + + if (buffer) { + encoding = null; + } + + let len = 0; + const ret = []; + const stream = new PassThrough({objectMode}); + + if (encoding) { + stream.setEncoding(encoding); + } + + stream.on('data', chunk => { + ret.push(chunk); + + if (objectMode) { + len = ret.length; + } else { + len += chunk.length; + } + }); + + stream.getBufferedValue = () => { + if (array) { + return ret; + } + + return buffer ? Buffer.concat(ret, len) : ret.join(''); + }; + + stream.getBufferedLength = () => len; + + return stream; +}; + + +/***/ }), + +/***/ 969: +/***/ (function(module, __unusedexports, __webpack_require__) { + +var wrappy = __webpack_require__(11) +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} + /***/ }), @@ -5171,7 +11165,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -const tr = __importStar(__webpack_require__(9)); +const tr = __importStar(__webpack_require__(686)); /** * Exec a command. * Output will be streamed to the live console. diff --git a/package-lock.json b/package-lock.json index 09facab..48b5000 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,13 @@ "@actions/io": "^1.0.1", "semver": "^6.1.0", "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } } }, "@babel/code-frame": { @@ -1071,6 +1078,111 @@ "fastq": "^1.6.0" } }, + "@octokit/auth-token": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.2.tgz", + "integrity": "sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ==", + "requires": { + "@octokit/types": "^5.0.0" + } + }, + "@octokit/core": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.1.0.tgz", + "integrity": "sha512-yPyQSmxIXLieEIRikk2w8AEtWkFdfG/LXcw1KvEtK3iP0ENZLW/WYQmdzOKqfSaLhooz4CJ9D+WY79C8ZliACw==", + "requires": { + "@octokit/auth-token": "^2.4.0", + "@octokit/graphql": "^4.3.1", + "@octokit/request": "^5.4.0", + "@octokit/types": "^5.0.0", + "before-after-hook": "^2.1.0", + "universal-user-agent": "^5.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.3.tgz", + "integrity": "sha512-Y900+r0gIz+cWp6ytnkibbD95ucEzDSKzlEnaWS52hbCDNcCJYO5mRmWW7HRAnDc7am+N/5Lnd8MppSaTYx1Yg==", + "requires": { + "@octokit/types": "^5.0.0", + "is-plain-object": "^3.0.0", + "universal-user-agent": "^5.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==" + } + } + }, + "@octokit/graphql": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.5.1.tgz", + "integrity": "sha512-qgMsROG9K2KxDs12CO3bySJaYoUu2aic90qpFrv7A8sEBzZ7UFGvdgPKiLw5gOPYEYbS0Xf8Tvf84tJutHPulQ==", + "requires": { + "@octokit/request": "^5.3.0", + "@octokit/types": "^5.0.0", + "universal-user-agent": "^5.0.0" + } + }, + "@octokit/plugin-paginate-rest": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.2.3.tgz", + "integrity": "sha512-eKTs91wXnJH8Yicwa30jz6DF50kAh7vkcqCQ9D7/tvBAP5KKkg6I2nNof8Mp/65G0Arjsb4QcOJcIEQY+rK1Rg==", + "requires": { + "@octokit/types": "^5.0.0" + } + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.0.0.tgz", + "integrity": "sha512-emS6gysz4E9BNi9IrCl7Pm4kR+Az3MmVB0/DoDCmF4U48NbYG3weKyDlgkrz6Jbl4Mu4nDx8YWZwC4HjoTdcCA==", + "requires": { + "@octokit/types": "^5.0.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.5.tgz", + "integrity": "sha512-atAs5GAGbZedvJXXdjtKljin+e2SltEs48B3naJjqWupYl2IUBbB/CJisyjbNHcKpHzb3E+OYEZ46G8eakXgQg==", + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.0.0", + "@octokit/types": "^5.0.0", + "deprecation": "^2.0.0", + "is-plain-object": "^3.0.0", + "node-fetch": "^2.3.0", + "once": "^1.4.0", + "universal-user-agent": "^5.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==" + } + } + }, + "@octokit/request-error": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.2.tgz", + "integrity": "sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw==", + "requires": { + "@octokit/types": "^5.0.1", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/types": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.0.1.tgz", + "integrity": "sha512-GorvORVwp244fGKEt3cgt/P+M0MGy4xEDbckw+K5ojEezxyMDgCaYPKVct+/eWQfZXOT7uq0xRpmrl/+hliabA==", + "requires": { + "@types/node": ">= 8" + } + }, "@sinonjs/commons": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", @@ -1195,8 +1307,7 @@ "@types/node": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.1.tgz", - "integrity": "sha512-FAYBGwC+W6F9+huFIDtn43cpy7+SzG+atzRiTfdp3inUKL2hXnd4rG8hylJLIh4+hqrQy1P17kvJByE/z825hA==", - "dev": true + "integrity": "sha512-FAYBGwC+W6F9+huFIDtn43cpy7+SzG+atzRiTfdp3inUKL2hXnd4rG8hylJLIh4+hqrQy1P17kvJByE/z825hA==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -1810,6 +1921,11 @@ "tweetnacl": "^0.14.3" } }, + "before-after-hook": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", + "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2289,6 +2405,11 @@ "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc=", "dev": true }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -2356,7 +2477,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -2909,7 +3029,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, "requires": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -2924,7 +3043,6 @@ "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -2936,20 +3054,17 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, "requires": { "shebang-regex": "^1.0.0" } @@ -2957,14 +3072,12 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -3380,7 +3493,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, "requires": { "pump": "^3.0.0" } @@ -3967,8 +4079,7 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, "is-string": { "version": "1.0.5", @@ -4016,8 +4127,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", @@ -5508,6 +5618,11 @@ "tslib": "^1.10.0" } }, + "macos-release": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.4.0.tgz", + "integrity": "sha512-ko6deozZYiAkqa/0gmcsz+p4jSy3gY7/ZsCEokPaYd8k+6/aXGkiTgr61+Owup7Sf+xjqW8u2ElhoM9SEcEfuA==" + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -5675,8 +5790,7 @@ "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "no-case": { "version": "3.0.3", @@ -5691,8 +5805,7 @@ "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", - "dev": true + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" }, "node-int64": { "version": "0.4.0", @@ -5770,7 +5883,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, "requires": { "path-key": "^2.0.0" }, @@ -5778,8 +5890,7 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" } } }, @@ -5913,7 +6024,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -5941,6 +6051,15 @@ "word-wrap": "^1.2.3" } }, + "os-name": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", + "requires": { + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -5956,8 +6075,7 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-limit": { "version": "2.3.0", @@ -6185,7 +6303,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -6402,6 +6519,12 @@ "psl": "^1.1.28", "punycode": "^2.1.1" } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true } } }, @@ -6776,8 +6899,7 @@ "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "sisteransi": { "version": "1.0.5", @@ -7208,8 +7330,7 @@ "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, "strip-final-newline": { "version": "2.0.0", @@ -7537,6 +7658,14 @@ "set-value": "^2.0.1" } }, + "universal-user-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-5.0.0.tgz", + "integrity": "sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q==", + "requires": { + "os-name": "^3.1.0" + } + }, "unixify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", @@ -7608,9 +7737,9 @@ "dev": true }, "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" }, "v8-compile-cache": { "version": "2.1.1", @@ -7752,6 +7881,14 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "windows-release": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.1.tgz", + "integrity": "sha512-Pngk/RDCaI/DkuHPlGTdIkDiTAnAkyMjoQMZqRsxydNl1qGXNIoZrB7RK8g53F2tEgQBMqQJHQdYZuQEEAu54A==", + "requires": { + "execa": "^1.0.0" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -7772,8 +7909,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", diff --git a/package.json b/package.json index b33d4c5..53b4b4f 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,11 @@ "@actions/core": "1.2.4", "@actions/exec": "1.0.4", "@actions/tool-cache": "1.3.4", - "is-docker": "2.0.0" + "@octokit/core": "3.1.0", + "@octokit/plugin-paginate-rest": "2.2.3", + "@octokit/plugin-rest-endpoint-methods": "4.0.0", + "is-docker": "2.0.0", + "uuid": "8.2.0" }, "devDependencies": { "@types/jest": "25.2.2", diff --git a/src/create-or-update-branch.ts b/src/create-or-update-branch.ts new file mode 100644 index 0000000..03fb852 --- /dev/null +++ b/src/create-or-update-branch.ts @@ -0,0 +1,192 @@ +import * as core from '@actions/core' +import {GitCommandManager} from './git-command-manager' +import {v4 as uuidv4} from 'uuid' + +const CHERRYPICK_EMPTY = + 'The previous cherry-pick is now empty, possibly due to conflict resolution.' + +export async function tryFetch( + git: GitCommandManager, + branch: string +): Promise { + try { + await git.fetch([`${branch}:refs/remotes/origin/${branch}`]) + return true + } catch { + return false + } +} + +// Return true if branch2 is ahead of branch1 +async function isAhead( + git: GitCommandManager, + branch1: string, + branch2: string +): Promise { + const result = await git.revList( + [`${branch1}...${branch2}`], + ['--right-only', '--count'] + ) + return Number(result) > 0 +} + +// Return true if branch2 is behind branch1 +async function isBehind( + git: GitCommandManager, + branch1: string, + branch2: string +): Promise { + const result = await git.revList( + [`${branch1}...${branch2}`], + ['--left-only', '--count'] + ) + return Number(result) > 0 +} + +// Return true if branch2 is even with branch1 +async function isEven( + git: GitCommandManager, + branch1: string, + branch2: string +): Promise { + return ( + !(await isAhead(git, branch1, branch2)) && + !(await isBehind(git, branch1, branch2)) + ) +} + +async function hasDiff( + git: GitCommandManager, + branch1: string, + branch2: string +): Promise { + const result = await git.diff([`${branch1}..${branch2}`]) + return result.length > 0 +} + +function splitLines(multilineString: string): string[] { + return multilineString + .split('\n') + .map(s => s.trim()) + .filter(x => x !== '') +} + +export async function createOrUpdateBranch( + git: GitCommandManager, + commitMessage: string, + baseInput: string, + branch: string +): Promise { + // Get the working base. This may or may not be the actual base. + const workingBase = await git.symbolicRef('HEAD', ['--short']) + // If the base is not specified it is assumed to be the working base. + const base = baseInput ? baseInput : workingBase + + // Set the default return values + const result: CreateOrUpdateBranchResult = { + action: 'none', + base: base, + hasDiffWithBase: false + } + + // Save the working base changes to a temporary branch + const tempBranch = uuidv4() + await git.checkout(tempBranch, 'HEAD') + // Commit any uncomitted changes + if (await git.isDirty(true)) { + core.info('Uncommitted changes found. Adding a commit.') + await git.exec(['add', '-A']) + await git.commit(['-m', commitMessage]) + } + + // Perform fetch and reset the working base + // Commits made during the workflow will be removed + await git.fetch([`${workingBase}:${workingBase}`], 'origin', ['--force']) + + // If the working base is not the base, rebase the temp branch commits + if (workingBase != base) { + core.info( + `Rebasing commits made to branch '${workingBase}' on to base branch '${base}'` + ) + // Checkout the actual base + await git.fetch([`${base}:${base}`], 'origin', ['--force']) + await git.checkout(base) + // Cherrypick commits from the temporary branch starting from the working base + const commits = await git.revList( + [`${workingBase}..${tempBranch}`, '.'], + ['--reverse'] + ) + for (const commit of splitLines(commits)) { + const result = await git.cherryPick( + ['--strategy=recursive', '--strategy-option=theirs', commit], + true + ) + if (result.exitCode != 0 && !result.stderr.includes(CHERRYPICK_EMPTY)) { + throw new Error(`Unexpected error: ${result.stderr}`) + } + } + // Reset the temp branch to the working index + await git.checkout(tempBranch, 'HEAD') + // Reset the base + await git.fetch([`${base}:${base}`], 'origin', ['--force']) + } + + // Try to fetch the pull request branch + if (!(await tryFetch(git, branch))) { + // The pull request branch does not exist + core.info(`Pull request branch '${branch}' does not exist yet.`) + // Create the pull request branch + await git.checkout(branch, 'HEAD') + // Check if the pull request branch is ahead of the base + result.hasDiffWithBase = await isAhead(git, base, branch) + if (result.hasDiffWithBase) { + result.action = 'created' + core.info(`Created branch '${branch}'`) + } else { + core.info( + `Branch '${branch}' is not ahead of base '${base}' and will not be created` + ) + } + } else { + // The pull request branch exists + core.info( + `Pull request branch '${branch}' already exists as remote branch 'origin/${branch}'` + ) + // Checkout the pull request branch + await git.checkout(branch) + + if (await hasDiff(git, branch, tempBranch)) { + // If the branch differs from the recreated temp version then the branch is reset + // For changes on base this action is similar to a rebase of the pull request branch + core.info(`Resetting '${branch}'`) + // Alternatively, git switch -C branch tempBranch + await git.checkout(branch, tempBranch) + } + + // Check if the pull request branch has been updated + // If the branch was reset or updated it will be ahead + // It may be behind if a reset now results in no diff with the base + if (!(await isEven(git, `origin/${branch}`, branch))) { + result.action = 'updated' + core.info(`Updated branch '${branch}'`) + } else { + core.info( + `Branch '${branch}' is even with its remote and will not be updated` + ) + } + + // Check if the pull request branch is ahead of the base + result.hasDiffWithBase = await isAhead(git, base, branch) + } + + // Delete the temporary branch + await git.exec(['branch', '--delete', '--force', tempBranch]) + + return result +} + +interface CreateOrUpdateBranchResult { + action: string + base: string + hasDiffWithBase: boolean +} diff --git a/src/create-pull-request.ts b/src/create-pull-request.ts new file mode 100644 index 0000000..50f2a46 --- /dev/null +++ b/src/create-pull-request.ts @@ -0,0 +1,232 @@ +import * as core from '@actions/core' +import {createOrUpdateBranch} from './create-or-update-branch' +import {GitHubHelper} from './github-helper' +import {GitCommandManager} from './git-command-manager' +import {ConfigOption, GitConfigHelper} from './git-config-helper' +import {GitIdentityHelper} from './git-identity-helper' +import * as utils from './utils' + +const EXTRAHEADER_OPTION = 'http.https://github.com/.extraheader' +const EXTRAHEADER_VALUE_REGEX = '^AUTHORIZATION:' + +const DEFAULT_COMMIT_MESSAGE = '[create-pull-request] automated change' +const DEFAULT_TITLE = 'Changes by create-pull-request action' +const DEFAULT_BODY = + 'Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action' +const DEFAULT_BRANCH = 'create-pull-request/patch' + +export interface Inputs { + token: string + path: string + commitMessage: string + committer: string + author: string + title: string + body: string + labels: string[] + assignees: string[] + reviewers: string[] + teamReviewers: string[] + milestone: number + draft: boolean + branch: string + requestToParent: boolean + base: string + branchSuffix: string +} + +export async function createPullRequest(inputs: Inputs): Promise { + let gitConfigHelper + let extraHeaderOption = new ConfigOption() + try { + // Get the repository path + const repoPath = utils.getRepoPath(inputs.path) + // Create a git command manager + const git = await GitCommandManager.create(repoPath) + // Unset and save the extraheader config option if it exists + gitConfigHelper = new GitConfigHelper(git) + extraHeaderOption = await gitConfigHelper.getAndUnsetConfigOption( + EXTRAHEADER_OPTION, + EXTRAHEADER_VALUE_REGEX + ) + + //github_token = inputs.token + //path = repoPath + + // Set defaults + inputs.commitMessage = inputs.commitMessage + ? inputs.commitMessage + : DEFAULT_COMMIT_MESSAGE + inputs.title = inputs.title ? inputs.title : DEFAULT_TITLE + inputs.body = inputs.body ? inputs.body : DEFAULT_BODY + inputs.branch = inputs.branch ? inputs.branch : DEFAULT_BRANCH + + // Determine the GitHub repository from git config + // This will be the target repository for the pull request branch + const remoteOriginUrlConfig = await gitConfigHelper.getConfigOption( + 'remote.origin.url' + ) + const remote = await utils.getRemoteDetail(remoteOriginUrlConfig.value) + core.info( + `Pull request branch target repository set to ${remote.repository}` + ) + + if (remote.protocol == 'HTTPS') { + core.debug('Using HTTPS protocol') + // Encode and configure the basic credential for HTTPS access + const basicCredential = Buffer.from( + `x-access-token:${inputs.token}`, + 'utf8' + ).toString('base64') + core.setSecret(basicCredential) + git.setAuthGitOptions([ + '-c', + `http.https://github.com/.extraheader=AUTHORIZATION: basic ${basicCredential}` + ]) + } + + // Determine if the checked out ref is a valid base for a pull request + // The action needs the checked out HEAD ref to be a branch + // This check will fail in the following cases: + // - HEAD is detached + // - HEAD is a merge commit (pull_request events) + // - HEAD is a tag + const symbolicRefResult = await git.exec( + ['symbolic-ref', 'HEAD', '--short'], + true + ) + if (symbolicRefResult.exitCode != 0) { + core.debug(`${symbolicRefResult.stderr}`) + throw new Error( + 'The checked out ref is not a valid base for a pull request. Unable to continue.' + ) + } + const workingBase = symbolicRefResult.stdout.trim() + + // Exit if the working base is a PR branch created by this action. + // This may occur when using a PAT instead of GITHUB_TOKEN because + // a PAT allows workflow actions to trigger further events. + if (workingBase.startsWith(inputs.branch)) { + throw new Error( + `Working base branch '${workingBase}' was created by this action. Unable to continue.` + ) + } + + // Apply the branch suffix if set + if (inputs.branchSuffix) { + switch (inputs.branchSuffix) { + case 'short-commit-hash': + // Suffix with the short SHA1 hash + inputs.branch = `${inputs.branch}-${await git.revParse('HEAD', [ + '--short' + ])}` + break + case 'timestamp': + // Suffix with the current timestamp + inputs.branch = `${inputs.branch}-${utils.secondsSinceEpoch()}` + break + case 'random': + // Suffix with a 7 character random string + inputs.branch = `${inputs.branch}-${utils.randomString()}` + break + default: + throw new Error( + `Branch suffix '${inputs.branchSuffix}' is not a valid value. Unable to continue.` + ) + } + } + + // Output head branch + core.info( + `Pull request branch to create or update set to '${inputs.branch}'` + ) + + // Determine the committer and author + const gitIdentityHelper = new GitIdentityHelper(git) + const identity = await gitIdentityHelper.getIdentity( + inputs.author, + inputs.committer + ) + git.setIdentityGitOptions([ + '-c', + `author.name=${identity.authorName}`, + '-c', + `author.email=${identity.authorEmail}`, + '-c', + `committer.name=${identity.committerName}`, + '-c', + `committer.email=${identity.committerEmail}` + ]) + core.info( + `Configured git committer as '${identity.committerName} <${identity.committerEmail}>'` + ) + core.info( + `Configured git author as '${identity.authorName} <${identity.authorEmail}>'` + ) + + // Create or update the pull request branch + const result = await createOrUpdateBranch( + git, + inputs.commitMessage, + inputs.base, + inputs.branch + ) + + if (['created', 'updated'].includes(result.action)) { + // The branch was created or updated + core.info(`Pushing pull request branch to 'origin/${inputs.branch}'`) + await git.push(['--force', 'origin', `HEAD:refs/heads/${inputs.branch}`]) + + // Set the base. It would have been '' if not specified as an input + inputs.base = result.base + + if (result.hasDiffWithBase) { + // Create or update the pull request + const githubHelper = new GitHubHelper(inputs.token) + await githubHelper.createOrUpdatePullRequest(inputs, remote.repository) + // coupr.create_or_update_pull_request( + // github_token, + // github_repository, + // branch, + // base, + // title, + // body, + // os.environ.get("CPR_LABELS"), + // os.environ.get("CPR_ASSIGNEES"), + // os.environ.get("CPR_MILESTONE"), + // os.environ.get("CPR_REVIEWERS"), + // os.environ.get("CPR_TEAM_REVIEWERS"), + // os.environ.get("CPR_PROJECT_NAME"), + // os.environ.get("CPR_PROJECT_COLUMN_NAME"), + // os.environ.get("CPR_DRAFT"), + // os.environ.get("CPR_REQUEST_TO_PARENT"), + // ) + } else { + // If there is no longer a diff with the base delete the branch + core.info( + `Branch '${inputs.branch}' no longer differs from base branch '${inputs.base}'` + ) + core.info(`Closing pull request and deleting branch '${inputs.branch}'`) + await git.push([ + '--delete', + '--force', + 'origin', + `refs/heads/${inputs.branch}` + ]) + } + } + } catch (error) { + core.setFailed(error.message) + } finally { + // Restore the extraheader config option + if (extraHeaderOption.value != '') { + if ( + await gitConfigHelper.addConfigOption( + EXTRAHEADER_OPTION, + extraHeaderOption.value + ) + ) + core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`) + } + } +} diff --git a/src/git-command-manager.ts b/src/git-command-manager.ts new file mode 100644 index 0000000..2125533 --- /dev/null +++ b/src/git-command-manager.ts @@ -0,0 +1,258 @@ +import * as exec from '@actions/exec' +import * as io from '@actions/io' + +const tagsRefSpec = '+refs/tags/*:refs/tags/*' + +export class GitCommandManager { + private gitPath: string + private workingDirectory: string + // Git options used when commands require auth + private authGitOptions?: string[] + // Git options used when commands require an identity + private identityGitOptions?: string[] + + private constructor(workingDirectory: string, gitPath: string) { + this.workingDirectory = workingDirectory + this.gitPath = gitPath + } + + static async create(workingDirectory: string): Promise { + const gitPath = await io.which('git', true) + return new GitCommandManager(workingDirectory, gitPath) + } + + setAuthGitOptions(authGitOptions: string[]): void { + this.authGitOptions = authGitOptions + } + + setIdentityGitOptions(identityGitOptions: string[]): void { + this.identityGitOptions = identityGitOptions + } + + async checkout(ref: string, startPoint?: string): Promise { + const args = ['checkout', '--progress'] + if (startPoint) { + args.push('-B', ref, startPoint) + } else { + args.push(ref) + } + await this.exec(args) + } + + async cherryPick( + options?: string[], + allowAllExitCodes = false + ): Promise { + const args = ['cherry-pick'] + if (this.identityGitOptions) { + args.unshift(...this.identityGitOptions) + } + + if (options) { + args.push(...options) + } + + return await this.exec(args, allowAllExitCodes) + } + + async commit(options?: string[]): Promise { + const args = ['commit'] + if (this.identityGitOptions) { + args.unshift(...this.identityGitOptions) + } + + if (options) { + args.push(...options) + } + + await this.exec(args) + } + + async diff(options?: string[]): Promise { + const args = ['-c', 'core.pager=cat', 'diff'] + if (options) { + args.push(...options) + } + const output = await this.exec(args) + return output.stdout.trim() + } + + async fetch( + refSpec: string[], + remoteName?: string, + options?: string[] + ): Promise { + const args = ['-c', 'protocol.version=2'] + if (this.authGitOptions) { + args.push(...this.authGitOptions) + } + args.push('fetch') + + if (!refSpec.some(x => x === tagsRefSpec)) { + args.push('--no-tags') + } + + args.push('--progress', '--no-recurse-submodules') + + if (options) { + args.push(...options) + } + + if (remoteName) { + args.push(remoteName) + } else { + args.push('origin') + } + for (const arg of refSpec) { + args.push(arg) + } + + await this.exec(args) + } + + getWorkingDirectory(): string { + return this.workingDirectory + } + + async isDirty(untracked: boolean): Promise { + const diffArgs = ['--abbrev=40', '--full-index', '--raw'] + // Check staged changes + if (await this.diff([...diffArgs, '--staged'])) { + return true + } + // Check working index changes + if (await this.diff(diffArgs)) { + return true + } + // Check untracked changes + if (untracked && (await this.status(['--porcelain', '-unormal']))) { + return true + } + return false + } + + async push(options?: string[]): Promise { + const args = ['push'] + if (this.authGitOptions) { + args.unshift(...this.authGitOptions) + } + + if (options) { + args.push(...options) + } + + await this.exec(args) + } + + async revList( + commitExpression: string[], + options?: string[] + ): Promise { + const args = ['rev-list'] + if (options) { + args.push(...options) + } + args.push(...commitExpression) + const output = await this.exec(args) + return output.stdout.trim() + } + + async revParse(ref: string, options?: string[]): Promise { + const args = ['rev-parse'] + if (options) { + args.push(...options) + } + args.push(ref) + const output = await this.exec(args) + return output.stdout.trim() + } + + async status(options?: string[]): Promise { + const args = ['status'] + if (options) { + args.push(...options) + } + const output = await this.exec(args) + return output.stdout.trim() + } + + async symbolicRef(ref: string, options?: string[]): Promise { + const args = ['symbolic-ref', ref] + if (options) { + args.push(...options) + } + const output = await this.exec(args) + return output.stdout.trim() + } + + async tryConfigUnset( + configKey: string, + globalConfig?: boolean + ): Promise { + const output = await this.exec( + [ + 'config', + globalConfig ? '--global' : '--local', + '--unset-all', + configKey + ], + true + ) + return output.exitCode === 0 + } + + async tryGetFetchUrl(): Promise { + const output = await this.exec( + ['config', '--local', '--get', 'remote.origin.url'], + true + ) + + if (output.exitCode !== 0) { + return '' + } + + const stdout = output.stdout.trim() + if (stdout.includes('\n')) { + return '' + } + + return stdout + } + + async exec(args: string[], allowAllExitCodes = false): Promise { + const result = new GitOutput() + + const env = {} + for (const key of Object.keys(process.env)) { + env[key] = process.env[key] + } + + const stdout: string[] = [] + const stderr: string[] = [] + + const options = { + cwd: this.workingDirectory, + env, + ignoreReturnCode: allowAllExitCodes, + listeners: { + stdout: (data: Buffer) => { + stdout.push(data.toString()) + }, + stderr: (data: Buffer) => { + stderr.push(data.toString()) + } + } + } + + result.exitCode = await exec.exec(`"${this.gitPath}"`, args, options) + result.stdout = stdout.join('') + result.stderr = stderr.join('') + return result + } +} + +class GitOutput { + stdout = '' + stderr = '' + exitCode = 0 +} diff --git a/src/git-config-helper.ts b/src/git-config-helper.ts new file mode 100644 index 0000000..25a9fbc --- /dev/null +++ b/src/git-config-helper.ts @@ -0,0 +1,64 @@ +import * as core from '@actions/core' +import {GitCommandManager} from './git-command-manager' + +export class ConfigOption { + name = '' + value = '' +} + +export class GitConfigHelper { + private git: GitCommandManager + + constructor(git: GitCommandManager) { + this.git = git + } + + async addConfigOption(name: string, value: string): Promise { + const result = await this.git.exec( + ['config', '--local', '--add', name, value], + true + ) + return result.exitCode === 0 + } + + async unsetConfigOption(name: string, valueRegex = '.'): Promise { + const result = await this.git.exec( + ['config', '--local', '--unset', name, valueRegex], + true + ) + return result.exitCode === 0 + } + + async configOptionExists(name: string, valueRegex = '.'): Promise { + const result = await this.git.exec( + ['config', '--local', '--name-only', '--get-regexp', name, valueRegex], + true + ) + return result.exitCode === 0 + } + + async getConfigOption(name: string, valueRegex = '.'): Promise { + const option = new ConfigOption() + const result = await this.git.exec( + ['config', '--local', '--get-regexp', name, valueRegex], + true + ) + option.name = name + option.value = result.stdout.trim().split(`${name} `)[1] + return option + } + + async getAndUnsetConfigOption( + name: string, + valueRegex = '.' + ): Promise { + if (await this.configOptionExists(name, valueRegex)) { + const option = await this.getConfigOption(name, valueRegex) + if (await this.unsetConfigOption(name, valueRegex)) { + core.debug(`Unset config option '${name}'`) + return option + } + } + return new ConfigOption() + } +} diff --git a/src/git-identity-helper.ts b/src/git-identity-helper.ts new file mode 100644 index 0000000..f9b260f --- /dev/null +++ b/src/git-identity-helper.ts @@ -0,0 +1,105 @@ +import * as core from '@actions/core' +import {GitCommandManager} from './git-command-manager' +import {GitConfigHelper} from './git-config-helper' +import * as utils from './utils' + +// Default the committer and author to the GitHub Actions bot +const DEFAULT_COMMITTER = 'GitHub ' +const DEFAULT_AUTHOR = + 'github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>' + +interface GitIdentity { + authorName: string + authorEmail: string + committerName: string + committerEmail: string +} + +export class GitIdentityHelper { + private git: GitCommandManager + + constructor(git: GitCommandManager) { + this.git = git + } + + private async getGitIdentityFromConfig(): Promise { + const gitConfigHelper = new GitConfigHelper(this.git) + + if ( + (await gitConfigHelper.configOptionExists('user.name')) && + (await gitConfigHelper.configOptionExists('user.email')) + ) { + const userName = await gitConfigHelper.getConfigOption('user.name') + const userEmail = await gitConfigHelper.getConfigOption('user.email') + return { + authorName: userName.value, + authorEmail: userEmail.value, + committerName: userName.value, + committerEmail: userEmail.value + } + } + + if ( + (await gitConfigHelper.configOptionExists('committer.name')) && + (await gitConfigHelper.configOptionExists('committer.email')) && + (await gitConfigHelper.configOptionExists('author.name')) && + (await gitConfigHelper.configOptionExists('author.email')) + ) { + const committerName = await gitConfigHelper.getConfigOption( + 'committer.name' + ) + const committerEmail = await gitConfigHelper.getConfigOption( + 'committer.email' + ) + const authorName = await gitConfigHelper.getConfigOption('author.name') + const authorEmail = await gitConfigHelper.getConfigOption('author.email') + return { + authorName: authorName.value, + authorEmail: authorEmail.value, + committerName: committerName.value, + committerEmail: committerEmail.value + } + } + + return undefined + } + + async getIdentity(author: string, committer: string): Promise { + // If either committer or author is supplied they will be cross used + if (!committer && author) { + core.info('Supplied author will also be used as the committer.') + committer = author + } + if (!author && committer) { + core.info('Supplied committer will also be used as the author.') + author = committer + } + + // If no committer/author has been supplied, try and fetch identity + // configuration already existing in git config. + if (!committer && !author) { + const identity = await this.getGitIdentityFromConfig() + if (identity) { + core.info('Retrieved a pre-configured git identity.') + return identity + } + } + + // Set defaults if no committer/author has been supplied and no + // existing identity configuration was found. + if (!committer && !author) { + core.info('Action defaults set for the author and committer.') + committer = DEFAULT_COMMITTER + author = DEFAULT_AUTHOR + } + + const parsedAuthor = utils.parseDisplayNameEmail(author) + const parsedCommitter = utils.parseDisplayNameEmail(committer) + return { + authorName: parsedAuthor.name, + authorEmail: parsedAuthor.email, + committerName: parsedCommitter.name, + committerEmail: parsedCommitter.email + } + } +} diff --git a/src/git.ts b/src/git.ts deleted file mode 100644 index c205158..0000000 --- a/src/git.ts +++ /dev/null @@ -1,121 +0,0 @@ -import * as core from '@actions/core' -import * as exec from '@actions/exec' -import * as path from 'path' - -class GitOutput { - stdout = '' - exitCode = 0 -} - -export class ConfigOption { - name = '' - value = '' -} - -export function getRepoPath(relativePath?: string): string { - let githubWorkspacePath = process.env['GITHUB_WORKSPACE'] - if (!githubWorkspacePath) { - throw new Error('GITHUB_WORKSPACE not defined') - } - githubWorkspacePath = path.resolve(githubWorkspacePath) - core.debug(`githubWorkspacePath: ${githubWorkspacePath}`) - - let repoPath = githubWorkspacePath - if (relativePath) repoPath = path.resolve(repoPath, relativePath) - - core.debug(`repoPath: ${repoPath}`) - return repoPath -} - -export async function execGit( - repoPath: string, - args: string[], - ignoreReturnCode = false -): Promise { - const result = new GitOutput() - - const stdout: string[] = [] - const options = { - cwd: repoPath, - ignoreReturnCode: ignoreReturnCode, - listeners: { - stdout: (data: Buffer): void => { - stdout.push(data.toString()) - } - } - } - - result.exitCode = await exec.exec('git', args, options) - result.stdout = stdout.join('') - return result -} - -export async function addConfigOption( - repoPath: string, - name: string, - value: string -): Promise { - const result = await execGit( - repoPath, - ['config', '--local', '--add', name, value], - true - ) - return result.exitCode === 0 -} - -export async function unsetConfigOption( - repoPath: string, - name: string, - valueRegex = '.' -): Promise { - const result = await execGit( - repoPath, - ['config', '--local', '--unset', name, valueRegex], - true - ) - return result.exitCode === 0 -} - -export async function configOptionExists( - repoPath: string, - name: string, - valueRegex = '.' -): Promise { - const result = await execGit( - repoPath, - ['config', '--local', '--name-only', '--get-regexp', name, valueRegex], - true - ) - return result.exitCode === 0 -} - -export async function getConfigOption( - repoPath: string, - name: string, - valueRegex = '.' -): Promise { - const option = new ConfigOption() - const result = await execGit( - repoPath, - ['config', '--local', '--get-regexp', name, valueRegex], - true - ) - option.name = name - option.value = result.stdout.trim().split(`${name} `)[1] - return option -} - -export async function getAndUnsetConfigOption( - repoPath: string, - name: string, - valueRegex = '.' -): Promise { - if (await configOptionExists(repoPath, name, valueRegex)) { - const option = await getConfigOption(repoPath, name, valueRegex) - if (await unsetConfigOption(repoPath, name, valueRegex)) { - core.debug(`Unset config option '${name}'`) - return option - } - } - return new ConfigOption() -} diff --git a/src/github-helper.ts b/src/github-helper.ts new file mode 100644 index 0000000..32dd5d2 --- /dev/null +++ b/src/github-helper.ts @@ -0,0 +1,157 @@ +import * as core from '@actions/core' +import {Inputs} from './create-pull-request' +import {Octokit, OctokitOptions} from './octokit-client' + +const ERROR_PR_REVIEW_FROM_AUTHOR = + 'Review cannot be requested from pull request author' + +interface Repository { + owner: string + repo: string +} + +export class GitHubHelper { + private octokit: InstanceType + + constructor(token: string) { + const options: OctokitOptions = {} + if (token) { + options.auth = `${token}` + } + this.octokit = new Octokit(options) + } + + private parseRepository(repository: string): Repository { + const [owner, repo] = repository.split('/') + return { + owner: owner, + repo: repo + } + } + + private async createOrUpdate( + inputs: Inputs, + baseRepository: string, + headBranch: string + ): Promise { + // Try to create the pull request + try { + const {data: pull} = await this.octokit.pulls.create({ + ...this.parseRepository(baseRepository), + title: inputs.title, + head: headBranch, + base: inputs.base, + body: inputs.body, + draft: inputs.draft + }) + core.info( + `Created pull request #${pull.number} (${headBranch} => ${inputs.base})` + ) + return pull.number + } catch (e) { + if ( + !e.message || + !e.message.includes(`A pull request already exists for ${headBranch}`) + ) { + throw e + } + } + + // Update the pull request that exists for this branch and base + const {data: pulls} = await this.octokit.pulls.list({ + ...this.parseRepository(baseRepository), + state: 'open', + head: headBranch, + base: inputs.base + }) + const {data: pull} = await this.octokit.pulls.update({ + ...this.parseRepository(baseRepository), + pull_number: pulls[0].number, + title: inputs.title, + body: inputs.body, + draft: inputs.draft + }) + core.info( + `Updated pull request #${pull.number} (${headBranch} => ${inputs.base})` + ) + return pull.number + } + + async createOrUpdatePullRequest( + inputs: Inputs, + headRepository: string + ): Promise { + const {data: headRepo} = await this.octokit.repos.get({ + ...this.parseRepository(headRepository) + }) + + if (inputs.requestToParent && !headRepo.parent) { + throw new Error( + `The checked out repository is not a fork. Input 'request-to-parent' should be set to 'false'.` + ) + } + const baseRepository = inputs.requestToParent + ? headRepo.parent.full_name + : headRepository + + const headBranch = `${headRepo.owner.login}:${inputs.branch}` + + // Create or update the pull request + const pullNumber = await this.createOrUpdate( + inputs, + baseRepository, + headBranch + ) + + // Set output + core.setOutput('pull-request-number', pullNumber) + + // Set milestone, labels and assignees + const updateIssueParams = {} + if (inputs.milestone) { + updateIssueParams['milestone'] = inputs.milestone + core.info(`Applying milestone '${inputs.milestone}'`) + } + if (inputs.labels.length > 0) { + updateIssueParams['labels'] = inputs.labels + core.info(`Applying labels '${inputs.labels}'`) + } + if (inputs.assignees.length > 0) { + updateIssueParams['assignees'] = inputs.assignees + core.info(`Applying assignees '${inputs.assignees}'`) + } + if (Object.keys(updateIssueParams).length > 0) { + await this.octokit.issues.update({ + ...this.parseRepository(baseRepository), + issue_number: pullNumber, + ...updateIssueParams + }) + } + + // Request reviewers and team reviewers + const requestReviewersParams = {} + if (inputs.reviewers.length > 0) { + requestReviewersParams['reviewers'] = inputs.reviewers + core.info(`Requesting reviewers '${inputs.reviewers}'`) + } + if (inputs.teamReviewers.length > 0) { + requestReviewersParams['team_reviewers'] = inputs.teamReviewers + core.info(`Requesting team reviewers '${inputs.teamReviewers}'`) + } + if (Object.keys(requestReviewersParams).length > 0) { + try { + await this.octokit.pulls.requestReviewers({ + ...this.parseRepository(baseRepository), + pull_number: pullNumber, + ...requestReviewersParams + }) + } catch (e) { + if (e.message && e.message.includes(ERROR_PR_REVIEW_FROM_AUTHOR)) { + core.warning(ERROR_PR_REVIEW_FROM_AUTHOR) + } else { + throw e + } + } + } + } +} diff --git a/src/main.ts b/src/main.ts index 0e9c95a..0039668 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,56 +1,11 @@ import * as core from '@actions/core' -import * as exec from '@actions/exec' -import {isDocker} from './isDocker' -import {setupPython} from './setupPython' -import { - ConfigOption, - getRepoPath, - getAndUnsetConfigOption, - addConfigOption -} from './git' +import {Inputs, createPullRequest} from './create-pull-request' import {inspect} from 'util' - -const EXTRAHEADER_OPTION = 'http.https://github.com/.extraheader' -const EXTRAHEADER_VALUE_REGEX = '^AUTHORIZATION:' +import * as utils from './utils' async function run(): Promise { - let repoPath - let extraHeaderOption = new ConfigOption() try { - // Python assets - const cpr = `${__dirname}/cpr` - core.debug(`cpr: ${cpr}`) - - // Determine how to access python and pip - const {pip, python} = (function (): {pip: string; python: string} { - if (isDocker()) { - core.info('Running inside a Docker container') - // Python 3 assumed to be installed and on the PATH - return { - pip: 'pip3', - python: 'python3' - } - } else { - // Setup Python from the tool cache - setupPython('3.x', 'x64') - return { - pip: 'pip', - python: 'python' - } - } - })() - - // Install requirements - await exec.exec(pip, [ - 'install', - '--requirement', - `${cpr}/requirements.txt`, - '--no-index', - `--find-links=${__dirname}/vendor` - ]) - - // Fetch action inputs - const inputs = { + const inputs: Inputs = { token: core.getInput('token'), path: core.getInput('path'), commitMessage: core.getInput('commit-message'), @@ -58,71 +13,22 @@ async function run(): Promise { author: core.getInput('author'), title: core.getInput('title'), body: core.getInput('body'), - labels: core.getInput('labels'), - assignees: core.getInput('assignees'), - reviewers: core.getInput('reviewers'), - teamReviewers: core.getInput('team-reviewers'), - milestone: core.getInput('milestone'), - project: core.getInput('project'), - projectColumn: core.getInput('project-column'), - draft: core.getInput('draft'), + labels: utils.getInputAsArray('labels'), + assignees: utils.getInputAsArray('assignees'), + reviewers: utils.getInputAsArray('reviewers'), + teamReviewers: utils.getInputAsArray('team-reviewers'), + milestone: Number(core.getInput('milestone')), + draft: core.getInput('draft') === 'true', branch: core.getInput('branch'), - requestToParent: core.getInput('request-to-parent'), + requestToParent: core.getInput('request-to-parent') === 'true', base: core.getInput('base'), branchSuffix: core.getInput('branch-suffix') } core.debug(`Inputs: ${inspect(inputs)}`) - // Set environment variables from inputs. - if (inputs.token) process.env.GITHUB_TOKEN = inputs.token - if (inputs.path) process.env.CPR_PATH = inputs.path - if (inputs.commitMessage) - process.env.CPR_COMMIT_MESSAGE = inputs.commitMessage - if (inputs.committer) process.env.CPR_COMMITTER = inputs.committer - if (inputs.author) process.env.CPR_AUTHOR = inputs.author - if (inputs.title) process.env.CPR_TITLE = inputs.title - if (inputs.body) process.env.CPR_BODY = inputs.body - if (inputs.labels) process.env.CPR_LABELS = inputs.labels - if (inputs.assignees) process.env.CPR_ASSIGNEES = inputs.assignees - if (inputs.reviewers) process.env.CPR_REVIEWERS = inputs.reviewers - if (inputs.teamReviewers) - process.env.CPR_TEAM_REVIEWERS = inputs.teamReviewers - if (inputs.milestone) process.env.CPR_MILESTONE = inputs.milestone - if (inputs.project) process.env.CPR_PROJECT_NAME = inputs.project - if (inputs.projectColumn) - process.env.CPR_PROJECT_COLUMN_NAME = inputs.projectColumn - if (inputs.draft) process.env.CPR_DRAFT = inputs.draft - if (inputs.branch) process.env.CPR_BRANCH = inputs.branch - if (inputs.requestToParent) - process.env.CPR_REQUEST_TO_PARENT = inputs.requestToParent - if (inputs.base) process.env.CPR_BASE = inputs.base - if (inputs.branchSuffix) process.env.CPR_BRANCH_SUFFIX = inputs.branchSuffix - - // Get the repository path - repoPath = getRepoPath(inputs.path) - // Get the extraheader config option if it exists - extraHeaderOption = await getAndUnsetConfigOption( - repoPath, - EXTRAHEADER_OPTION, - EXTRAHEADER_VALUE_REGEX - ) - - // Execute create pull request - await exec.exec(python, [`${cpr}/create_pull_request.py`]) + await createPullRequest(inputs) } catch (error) { core.setFailed(error.message) - } finally { - // Restore the extraheader config option - if (extraHeaderOption.value != '') { - if ( - await addConfigOption( - repoPath, - EXTRAHEADER_OPTION, - extraHeaderOption.value - ) - ) - core.debug(`Restored config option '${EXTRAHEADER_OPTION}'`) - } } } diff --git a/src/octokit-client.ts b/src/octokit-client.ts new file mode 100644 index 0000000..5e82c5d --- /dev/null +++ b/src/octokit-client.ts @@ -0,0 +1,7 @@ +import {Octokit as Core} from '@octokit/core' +import {paginateRest} from '@octokit/plugin-paginate-rest' +import {restEndpointMethods} from '@octokit/plugin-rest-endpoint-methods' +export {RestEndpointMethodTypes} from '@octokit/plugin-rest-endpoint-methods' +export {OctokitOptions} from '@octokit/core/dist-types/types' + +export const Octokit = Core.plugin(paginateRest, restEndpointMethods) diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..a3b304c --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,107 @@ +import * as core from '@actions/core' +import * as path from 'path' + +export function getInputAsArray( + name: string, + options?: core.InputOptions +): string[] { + return getStringAsArray(core.getInput(name, options)) +} + +export function getStringAsArray(str: string): string[] { + return str + .split(/[\n,]+/) + .map(s => s.trim()) + .filter(x => x !== '') +} + +export function getRepoPath(relativePath?: string): string { + let githubWorkspacePath = process.env['GITHUB_WORKSPACE'] + if (!githubWorkspacePath) { + throw new Error('GITHUB_WORKSPACE not defined') + } + githubWorkspacePath = path.resolve(githubWorkspacePath) + core.debug(`githubWorkspacePath: ${githubWorkspacePath}`) + + let repoPath = githubWorkspacePath + if (relativePath) repoPath = path.resolve(repoPath, relativePath) + + core.debug(`repoPath: ${repoPath}`) + return repoPath +} + +interface RemoteDetail { + protocol: string + repository: string +} + +export function getRemoteDetail(remoteUrl: string): RemoteDetail { + // Parse the protocol and github repository from a URL + // e.g. HTTPS, peter-evans/create-pull-request + const httpsUrlPattern = /^https:\/\/.*@?github.com\/(.+\/.+)$/i + const sshUrlPattern = /^git@github.com:(.+\/.+).git$/i + + const httpsMatch = remoteUrl.match(httpsUrlPattern) + if (httpsMatch) { + return { + protocol: 'HTTPS', + repository: httpsMatch[1] + } + } + + const sshMatch = remoteUrl.match(sshUrlPattern) + if (sshMatch) { + return { + protocol: 'SSH', + repository: sshMatch[1] + } + } + + throw new Error( + `The format of '${remoteUrl}' is not a valid GitHub repository URL` + ) +} + +export function secondsSinceEpoch(): number { + const now = new Date() + return Math.round(now.getTime() / 1000) +} + +export function randomString(): string { + return Math.random().toString(36).substr(2, 7) +} + +interface DisplayNameEmail { + name: string + email: string +} + +export function parseDisplayNameEmail( + displayNameEmail: string +): DisplayNameEmail { + // Parse the name and email address from a string in the following format + // Display Name + const pattern = /^([^<]+)\s*<([^>]+)>$/i + + // Check we have a match + const match = displayNameEmail.match(pattern) + if (!match) { + throw new Error( + `The format of '${displayNameEmail}' is not a valid email address with display name` + ) + } + + // Check that name and email are not just whitespace + const name = match[1].trim() + const email = match[2].trim() + if (!name || !email) { + throw new Error( + `The format of '${displayNameEmail}' is not a valid email address with display name` + ) + } + + return { + name: name, + email: email + } +} From 803cc5ea8aaea8e78ee69423540d925e0b5bf365 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Thu, 16 Jul 2020 18:18:58 +0900 Subject: [PATCH 005/694] Remove python related code and artifacts --- .gitignore | 3 - dist/cpr/common.py | 48 -- dist/cpr/create_or_update_branch.py | 145 ----- dist/cpr/create_or_update_pull_request.py | 162 ----- dist/cpr/create_pull_request.py | 229 ------- dist/cpr/requirements.txt | 4 - dist/cpr/test_common.py | 69 -- dist/cpr/test_create_or_update_branch.py | 757 ---------------------- dist/vendor/Deprecated-1.2.10.tar.gz | Bin 2969723 -> 0 bytes dist/vendor/GitPython-3.1.2.tar.gz | Bin 430474 -> 0 bytes dist/vendor/PyGithub-1.51.tar.gz | Bin 141594 -> 0 bytes dist/vendor/PyJWT-1.7.1.tar.gz | Bin 41979 -> 0 bytes dist/vendor/certifi-2020.6.20.tar.gz | Bin 157997 -> 0 bytes dist/vendor/chardet-3.0.4.tar.gz | Bin 1868453 -> 0 bytes dist/vendor/gitdb-4.0.5.tar.gz | Bin 392815 -> 0 bytes dist/vendor/idna-2.9.tar.gz | Bin 175042 -> 0 bytes dist/vendor/requests-2.24.0.tar.gz | Bin 115071 -> 0 bytes dist/vendor/setuptools-46.4.0.zip | Bin 865912 -> 0 bytes dist/vendor/smmap-3.0.4.tar.gz | Bin 22459 -> 0 bytes dist/vendor/urllib3-1.25.9.tar.gz | Bin 254921 -> 0 bytes dist/vendor/wheel-0.34.2.tar.gz | Bin 58330 -> 0 bytes dist/vendor/wrapt-1.12.1.tar.gz | Bin 27488 -> 0 bytes package-lock.json | 6 +- package.json | 11 +- renovate.json | 9 - src/cpr/common.py | 48 -- src/cpr/create_or_update_branch.py | 145 ----- src/cpr/create_or_update_pull_request.py | 162 ----- src/cpr/create_pull_request.py | 229 ------- src/cpr/requirements.txt | 4 - src/cpr/test_common.py | 69 -- src/cpr/test_create_or_update_branch.py | 757 ---------------------- src/isDocker.ts | 22 - src/setupPython.ts | 50 -- 34 files changed, 9 insertions(+), 2920 deletions(-) delete mode 100644 dist/cpr/common.py delete mode 100644 dist/cpr/create_or_update_branch.py delete mode 100644 dist/cpr/create_or_update_pull_request.py delete mode 100644 dist/cpr/create_pull_request.py delete mode 100644 dist/cpr/requirements.txt delete mode 100644 dist/cpr/test_common.py delete mode 100644 dist/cpr/test_create_or_update_branch.py delete mode 100644 dist/vendor/Deprecated-1.2.10.tar.gz delete mode 100644 dist/vendor/GitPython-3.1.2.tar.gz delete mode 100644 dist/vendor/PyGithub-1.51.tar.gz delete mode 100644 dist/vendor/PyJWT-1.7.1.tar.gz delete mode 100644 dist/vendor/certifi-2020.6.20.tar.gz delete mode 100644 dist/vendor/chardet-3.0.4.tar.gz delete mode 100644 dist/vendor/gitdb-4.0.5.tar.gz delete mode 100644 dist/vendor/idna-2.9.tar.gz delete mode 100644 dist/vendor/requests-2.24.0.tar.gz delete mode 100644 dist/vendor/setuptools-46.4.0.zip delete mode 100644 dist/vendor/smmap-3.0.4.tar.gz delete mode 100644 dist/vendor/urllib3-1.25.9.tar.gz delete mode 100644 dist/vendor/wheel-0.34.2.tar.gz delete mode 100644 dist/vendor/wrapt-1.12.1.tar.gz delete mode 100644 renovate.json delete mode 100644 src/cpr/common.py delete mode 100644 src/cpr/create_or_update_branch.py delete mode 100644 src/cpr/create_or_update_pull_request.py delete mode 100755 src/cpr/create_pull_request.py delete mode 100644 src/cpr/requirements.txt delete mode 100644 src/cpr/test_common.py delete mode 100644 src/cpr/test_create_or_update_branch.py delete mode 100644 src/isDocker.ts delete mode 100644 src/setupPython.ts diff --git a/.gitignore b/.gitignore index a135bac..d352240 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,3 @@ -__pycache__ -.python-version - lib/ node_modules/ diff --git a/dist/cpr/common.py b/dist/cpr/common.py deleted file mode 100644 index faf0d03..0000000 --- a/dist/cpr/common.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 -import random -import re -import string - - -def get_random_string(length=7, chars=string.ascii_lowercase + string.digits): - return "".join(random.choice(chars) for _ in range(length)) - - -def parse_github_repository(url): - # Parse the protocol and github repository from a URL - # e.g. HTTPS, peter-evans/create-pull-request - https_pattern = re.compile(r"^https://.*@?github.com/(.+/.+)$") - ssh_pattern = re.compile(r"^git@github.com:(.+/.+).git$") - - match = https_pattern.match(url) - if match is not None: - return "HTTPS", match.group(1) - - match = ssh_pattern.match(url) - if match is not None: - return "SSH", match.group(1) - - raise ValueError(f"The format of '{url}' is not a valid GitHub repository URL") - - -def parse_display_name_email(display_name_email): - # Parse the name and email address from a string in the following format - # Display Name - pattern = re.compile(r"^([^<]+)\s*<([^>]+)>$") - - # Check we have a match - match = pattern.match(display_name_email) - if match is None: - raise ValueError( - f"The format of '{display_name_email}' is not a valid email address with display name" - ) - - # Check that name and email are not just whitespace - name = match.group(1).strip() - email = match.group(2).strip() - if len(name) == 0 or len(email) == 0: - raise ValueError( - f"The format of '{display_name_email}' is not a valid email address with display name" - ) - - return name, email diff --git a/dist/cpr/create_or_update_branch.py b/dist/cpr/create_or_update_branch.py deleted file mode 100644 index 2cb24d1..0000000 --- a/dist/cpr/create_or_update_branch.py +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env python3 -""" Create or Update Branch """ -import common as cmn -from git import Repo, GitCommandError -import os - - -CHERRYPICK_EMPTY = ( - "The previous cherry-pick is now empty, possibly due to conflict resolution." -) - - -def fetch_successful(repo, repo_url, branch): - try: - repo.git.fetch(repo_url, f"{branch}:refs/remotes/origin/{branch}") - except GitCommandError: - return False - return True - - -def is_ahead(repo, branch_1, branch_2): - # Return true if branch_2 is ahead of branch_1 - return ( - int(repo.git.rev_list("--right-only", "--count", f"{branch_1}...{branch_2}")) - > 0 - ) - - -def is_behind(repo, branch_1, branch_2): - # Return true if branch_2 is behind branch_1 - return ( - int(repo.git.rev_list("--left-only", "--count", f"{branch_1}...{branch_2}")) > 0 - ) - - -def is_even(repo, branch_1, branch_2): - # Return true if branch_2 is even with branch_1 - return not is_ahead(repo, branch_1, branch_2) and not is_behind( - repo, branch_1, branch_2 - ) - - -def has_diff(repo, branch_1, branch_2): - diff = repo.git.diff(f"{branch_1}..{branch_2}") - return len(diff) > 0 - - -def create_or_update_branch(repo, repo_url, commit_message, base, branch): - # Set the default return values - action = "none" - diff = False - - # Get the working base. This may or may not be the actual base. - working_base = repo.git.symbolic_ref("HEAD", "--short") - # If the base is not specified it is assumed to be the working base - if base is None: - base = working_base - - # Save the working base changes to a temporary branch - temp_branch = cmn.get_random_string(length=20) - repo.git.checkout("HEAD", b=temp_branch) - # Commit any uncomitted changes - if repo.is_dirty(untracked_files=True): - print(f"Uncommitted changes found. Adding a commit.") - repo.git.add("-A") - repo.git.commit(m=commit_message) - - # Perform fetch and reset the working base - # Commits made during the workflow will be removed - repo.git.fetch("--force", repo_url, f"{working_base}:{working_base}") - - # If the working base is not the base, rebase the temp branch commits - if working_base != base: - print( - f"Rebasing commits made to branch '{working_base}' on to base branch '{base}'" - ) - # Checkout the actual base - repo.git.fetch("--force", repo_url, f"{base}:{base}") - repo.git.checkout(base) - # Cherrypick commits from the temporary branch starting from the working base - commits = repo.git.rev_list("--reverse", f"{working_base}..{temp_branch}", ".") - for commit in commits.splitlines(): - try: - repo.git.cherry_pick( - "--strategy", - "recursive", - "--strategy-option", - "theirs", - f"{commit}", - ) - except GitCommandError as e: - if CHERRYPICK_EMPTY not in e.stderr: - print("Unexpected error: ", e) - raise - # Reset the temp branch to the working index - repo.git.checkout("-B", temp_branch, "HEAD") - # Reset the base - repo.git.fetch("--force", repo_url, f"{base}:{base}") - - # Try to fetch the pull request branch - if not fetch_successful(repo, repo_url, branch): - # The pull request branch does not exist - print(f"Pull request branch '{branch}' does not exist yet") - # Create the pull request branch - repo.git.checkout("HEAD", b=branch) - # Check if the pull request branch is ahead of the base - diff = is_ahead(repo, base, branch) - if diff: - action = "created" - print(f"Created branch '{branch}'") - else: - print( - f"Branch '{branch}' is not ahead of base '{base}' and will not be created" - ) - else: - # The pull request branch exists - print( - f"Pull request branch '{branch}' already exists as remote branch 'origin/{branch}'" - ) - # Checkout the pull request branch - repo.git.checkout(branch) - - if has_diff(repo, branch, temp_branch): - # If the branch differs from the recreated temp version then the branch is reset - # For changes on base this action is similar to a rebase of the pull request branch - print(f"Resetting '{branch}'") - repo.git.checkout("-B", branch, temp_branch) - # repo.git.switch("-C", branch, temp_branch) - - # Check if the pull request branch has been updated - # If the branch was reset or updated it will be ahead - # It may be behind if a reset now results in no diff with the base - if not is_even(repo, f"origin/{branch}", branch): - action = "updated" - print(f"Updated branch '{branch}'") - else: - print(f"Branch '{branch}' is even with its remote and will not be updated") - - # Check if the pull request branch is ahead of the base - diff = is_ahead(repo, base, branch) - - # Delete the temporary branch - repo.git.branch("--delete", "--force", temp_branch) - - return {"action": action, "diff": diff, "base": base} diff --git a/dist/cpr/create_or_update_pull_request.py b/dist/cpr/create_or_update_pull_request.py deleted file mode 100644 index a34b090..0000000 --- a/dist/cpr/create_or_update_pull_request.py +++ /dev/null @@ -1,162 +0,0 @@ -#!/usr/bin/env python3 -""" Create or Update Pull Request """ -from github import Github, GithubException -import os - - -def string_to_bool(str): - if str is None: - return False - else: - return str.lower() in [ - "true", - "1", - "t", - "y", - "yes", - "on", - ] - - -def cs_string_to_list(str): - # Split the comma separated string into a list - l = [i.strip() for i in str.split(",")] - # Remove empty strings - return list(filter(None, l)) - - -def create_project_card(github_repo, project_name, project_column_name, pull_request): - # Locate the project by name - project = None - for project_item in github_repo.get_projects("all"): - if project_item.name == project_name: - project = project_item - break - - if not project: - print("::error::Project not found. Unable to create project card.") - return - - # Locate the column by name - column = None - for column_item in project.get_columns(): - if column_item.name == project_column_name: - column = column_item - break - - if not column: - print("::error::Project column not found. Unable to create project card.") - return - - # Create a project card for the pull request - column.create_card(content_id=pull_request.id, content_type="PullRequest") - print( - "Added pull request #%d to project '%s' under column '%s'" - % (pull_request.number, project.name, column.name) - ) - - -def create_or_update_pull_request( - github_token, - github_repository, - branch, - base, - title, - body, - labels, - assignees, - milestone, - reviewers, - team_reviewers, - project_name, - project_column_name, - draft, - request_to_parent, -): - github_repo = head_repo = Github(github_token).get_repo(github_repository) - if string_to_bool(request_to_parent): - github_repo = github_repo.parent - if github_repo is None: - raise ValueError( - "The checked out repository is not a fork. Input 'request-to-parent' should be set to false." - ) - - head_branch = f"{head_repo.owner.login}:{branch}" - - # Create the pull request - try: - pull_request = github_repo.create_pull( - title=title, - body=body, - base=base, - head=head_branch, - draft=string_to_bool(draft), - ) - print( - f"Created pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})" - ) - except GithubException as e: - if e.status == 422: - # A pull request exists for this branch and base - # Get the pull request - pull_request = github_repo.get_pulls( - state="open", base=base, head=head_branch - )[0] - # Update title and body - pull_request.as_issue().edit(title=title, body=body) - print( - f"Updated pull request #{pull_request.number} ({head_branch} => {github_repo.owner.login}:{base})" - ) - else: - print(str(e)) - raise - - # Set the output variables - os.system(f"echo ::set-env name=PULL_REQUEST_NUMBER::{pull_request.number}") - os.system(f"echo ::set-output name=pull-request-number::{pull_request.number}") - # 'pr_number' is deprecated - os.system(f"echo ::set-output name=pr_number::{pull_request.number}") - - # Set labels, assignees and milestone - if labels is not None: - print(f"Applying labels '{labels}'") - pull_request.as_issue().edit(labels=cs_string_to_list(labels)) - if assignees is not None: - print(f"Applying assignees '{assignees}'") - pull_request.as_issue().edit(assignees=cs_string_to_list(assignees)) - if milestone is not None: - print(f"Applying milestone '{milestone}'") - milestone = github_repo.get_milestone(int(milestone)) - pull_request.as_issue().edit(milestone=milestone) - - # Set pull request reviewers - if reviewers is not None: - print(f"Requesting reviewers '{reviewers}'") - try: - pull_request.create_review_request(reviewers=cs_string_to_list(reviewers)) - except GithubException as e: - # Likely caused by "Review cannot be requested from pull request author." - if e.status == 422: - print("Request reviewers failed - {}".format(e.data["message"])) - - # Set pull request team reviewers - if team_reviewers is not None: - print(f"Requesting team reviewers '{team_reviewers}'") - pull_request.create_review_request( - team_reviewers=cs_string_to_list(team_reviewers) - ) - - # Create a project card for the pull request - if project_name is not None and project_column_name is not None: - try: - create_project_card( - github_repo, project_name, project_column_name, pull_request - ) - except GithubException as e: - # Likely caused by "Project already has the associated issue." - if e.status == 422: - print( - "Create project card failed - {}".format( - e.data["errors"][0]["message"] - ) - ) diff --git a/dist/cpr/create_pull_request.py b/dist/cpr/create_pull_request.py deleted file mode 100644 index ead7f02..0000000 --- a/dist/cpr/create_pull_request.py +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env python3 -""" Create Pull Request """ -import base64 -import common as cmn -import create_or_update_branch as coub -import create_or_update_pull_request as coupr -from git import Repo, GitCommandError -import json -import os -import sys -import time - - -# Default the committer and author to the GitHub Actions bot -DEFAULT_COMMITTER = "GitHub " -DEFAULT_AUTHOR = ( - "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" -) -DEFAULT_COMMIT_MESSAGE = "[create-pull-request] automated change" -DEFAULT_TITLE = "Changes by create-pull-request action" -DEFAULT_BODY = ( - "Automated changes by " - + "[create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action" -) -DEFAULT_BRANCH = "create-pull-request/patch" - - -def get_git_config_value(repo, name): - try: - return repo.git.config("--get", name) - except GitCommandError: - return None - - -def get_repository_detail(repo): - remote_origin_url = get_git_config_value(repo, "remote.origin.url") - if remote_origin_url is None: - raise ValueError("Failed to fetch 'remote.origin.url' from git config") - protocol, github_repository = cmn.parse_github_repository(remote_origin_url) - return remote_origin_url, protocol, github_repository - - -def git_user_config_is_set(repo): - name = get_git_config_value(repo, "user.name") - email = get_git_config_value(repo, "user.email") - - if name is not None and email is not None: - print(f"Git user already configured as '{name} <{email}>'") - return True - - committer_name = get_git_config_value(repo, "committer.name") - committer_email = get_git_config_value(repo, "committer.email") - author_name = get_git_config_value(repo, "author.name") - author_email = get_git_config_value(repo, "author.email") - - if ( - committer_name is not None - and committer_email is not None - and author_name is not None - and author_email is not None - ): - print( - f"Git committer already configured as '{committer_name} <{committer_email}>'" - ) - print(f"Git author already configured as '{author_name} <{author_email}>'") - return True - - return False - - -def set_committer_author(repo, committer, author): - # If either committer or author is supplied they will be cross used - if committer is None and author is not None: - print("Supplied author will also be used as the committer.") - committer = author - if author is None and committer is not None: - print("Supplied committer will also be used as the author.") - author = committer - - # If no committer/author has been supplied but user configuration already - # exists in git config we can exit and use the existing config as-is. - if committer is None and author is None: - if git_user_config_is_set(repo): - return - - # Set defaults if no committer/author has been supplied - if committer is None and author is None: - committer = DEFAULT_COMMITTER - author = DEFAULT_AUTHOR - - # Set git environment. This will not persist after the action completes. - committer_name, committer_email = cmn.parse_display_name_email(committer) - author_name, author_email = cmn.parse_display_name_email(author) - repo.git.update_environment( - GIT_COMMITTER_NAME=committer_name, - GIT_COMMITTER_EMAIL=committer_email, - GIT_AUTHOR_NAME=author_name, - GIT_AUTHOR_EMAIL=author_email, - ) - print(f"Configured git committer as '{committer_name} <{committer_email}>'") - print(f"Configured git author as '{author_name} <{author_email}>'") - - -# Get required environment variables -github_token = os.environ["GITHUB_TOKEN"] -# Get environment variables with defaults -path = os.getenv("CPR_PATH", os.getcwd()) -branch = os.getenv("CPR_BRANCH", DEFAULT_BRANCH) -commit_message = os.getenv("CPR_COMMIT_MESSAGE", DEFAULT_COMMIT_MESSAGE) -# Get environment variables with a default of 'None' -committer = os.environ.get("CPR_COMMITTER") -author = os.environ.get("CPR_AUTHOR") -base = os.environ.get("CPR_BASE") - -# Set the repo path -repo = Repo(path) - -# Determine the GitHub repository from git config -# This will be the target repository for the pull request -repo_url, protocol, github_repository = get_repository_detail(repo) -print(f"Target repository set to {github_repository}") - -if protocol == "HTTPS": - print(f"::debug::Using HTTPS protocol") - # Encode and configure the basic credential for HTTPS access - basic_credential = base64.b64encode( - f"x-access-token:{github_token}".encode("utf-8") - ).decode("utf-8") - # Mask the basic credential in logs and debug output - print(f"::add-mask::{basic_credential}") - repo.git.set_persistent_git_options( - c=f"http.https://github.com/.extraheader=AUTHORIZATION: basic {basic_credential}" - ) - -# Determine if the checked out ref is a valid base for a pull request -# The action needs the checked out HEAD ref to be a branch -# This check will fail in the following cases: -# - HEAD is detached -# - HEAD is a merge commit (pull_request events) -# - HEAD is a tag -try: - working_base = repo.git.symbolic_ref("HEAD", "--short") -except GitCommandError as e: - print(f"::debug::{e.stderr}") - print( - f"::error::The checked out ref is not a valid base for a pull request. " - + "Unable to continue. Exiting." - ) - sys.exit(1) - -# Exit if the working base is a PR branch created by this action. -# This may occur when using a PAT instead of GITHUB_TOKEN because -# a PAT allows workflow actions to trigger further events. -if working_base.startswith(branch): - print( - f"::error::Working base branch '{working_base}' was created by this action. " - + "Unable to continue. Exiting." - ) - sys.exit(1) - -# Fetch an optional environment variable to determine the branch suffix -branch_suffix = os.environ.get("CPR_BRANCH_SUFFIX") -if branch_suffix is not None: - if branch_suffix == "short-commit-hash": - # Suffix with the short SHA1 hash - branch = "{}-{}".format(branch, repo.git.rev_parse("--short", "HEAD")) - elif branch_suffix == "timestamp": - # Suffix with the current timestamp - branch = "{}-{}".format(branch, int(time.time())) - elif branch_suffix == "random": - # Suffix with a 7 character random string - branch = "{}-{}".format(branch, cmn.get_random_string()) - else: - print( - f"::error::Branch suffix '{branch_suffix}' is not a valid value. " - + "Unable to continue. Exiting." - ) - sys.exit(1) - -# Output head branch -print(f"Pull request branch to create or update set to '{branch}'") - -# Set the committer and author -try: - set_committer_author(repo, committer, author) -except ValueError as e: - print(f"::error::{e} " + "Unable to continue. Exiting.") - sys.exit(1) - -# Create or update the pull request branch -result = coub.create_or_update_branch(repo, repo_url, commit_message, base, branch) - -if result["action"] in ["created", "updated"]: - # The branch was created or updated - print(f"Pushing pull request branch to 'origin/{branch}'") - repo.git.push("--force", repo_url, f"HEAD:refs/heads/{branch}") - - # Set the base. It would have been 'None' if not specified as an input - base = result["base"] - - # If there is no longer a diff with the base delete the branch and exit - if not result["diff"]: - print(f"Branch '{branch}' no longer differs from base branch '{base}'") - print(f"Closing pull request and deleting branch '{branch}'") - repo.git.push("--delete", "--force", repo_url, f"refs/heads/{branch}") - sys.exit() - - # Fetch optional environment variables with default values - title = os.getenv("CPR_TITLE", DEFAULT_TITLE) - body = os.getenv("CPR_BODY", DEFAULT_BODY) - - # Create or update the pull request - coupr.create_or_update_pull_request( - github_token, - github_repository, - branch, - base, - title, - body, - os.environ.get("CPR_LABELS"), - os.environ.get("CPR_ASSIGNEES"), - os.environ.get("CPR_MILESTONE"), - os.environ.get("CPR_REVIEWERS"), - os.environ.get("CPR_TEAM_REVIEWERS"), - os.environ.get("CPR_PROJECT_NAME"), - os.environ.get("CPR_PROJECT_COLUMN_NAME"), - os.environ.get("CPR_DRAFT"), - os.environ.get("CPR_REQUEST_TO_PARENT"), - ) diff --git a/dist/cpr/requirements.txt b/dist/cpr/requirements.txt deleted file mode 100644 index 5afd424..0000000 --- a/dist/cpr/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -setuptools==46.4.0 -wheel==0.34.2 -GitPython==3.1.2 -PyGithub==1.51 diff --git a/dist/cpr/test_common.py b/dist/cpr/test_common.py deleted file mode 100644 index 9409258..0000000 --- a/dist/cpr/test_common.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python3 -""" Test Common """ -import common as cmn -import pytest - - -def test_get_random_string(): - assert len(cmn.get_random_string()) == 7 - assert len(cmn.get_random_string(length=20)) == 20 - - -def test_parse_github_repository_success(): - protocol, repository = cmn.parse_github_repository( - "https://github.com/peter-evans/create-pull-request" - ) - assert protocol == "HTTPS" - assert repository == "peter-evans/create-pull-request" - - protocol, repository = cmn.parse_github_repository( - "https://xxx:x-oauth-basic@github.com/peter-evans/create-pull-request" - ) - assert protocol == "HTTPS" - assert repository == "peter-evans/create-pull-request" - - protocol, repository = cmn.parse_github_repository( - "git@github.com:peter-evans/create-pull-request.git" - ) - assert protocol == "SSH" - assert repository == "peter-evans/create-pull-request" - - -def test_parse_github_repository_failure(): - url = "https://github.com/peter-evans" - with pytest.raises(ValueError) as e_info: - cmn.parse_github_repository(url) - assert ( - e_info.value.args[0] - == f"The format of '{url}' is not a valid GitHub repository URL" - ) - - -def test_parse_display_name_email_success(): - name, email = cmn.parse_display_name_email("abc def ") - assert name == "abc def" - assert email == "abc@def.com" - - name, email = cmn.parse_display_name_email( - "github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>" - ) - assert name == "github-actions[bot]" - assert email == "41898282+github-actions[bot]@users.noreply.github.com" - - -def test_parse_display_name_email_failure(): - display_name_email = "abc@def.com" - with pytest.raises(ValueError) as e_info: - cmn.parse_display_name_email(display_name_email) - assert ( - e_info.value.args[0] - == f"The format of '{display_name_email}' is not a valid email address with display name" - ) - - display_name_email = " < >" - with pytest.raises(ValueError) as e_info: - cmn.parse_display_name_email(display_name_email) - assert ( - e_info.value.args[0] - == f"The format of '{display_name_email}' is not a valid email address with display name" - ) diff --git a/dist/cpr/test_create_or_update_branch.py b/dist/cpr/test_create_or_update_branch.py deleted file mode 100644 index a0f400c..0000000 --- a/dist/cpr/test_create_or_update_branch.py +++ /dev/null @@ -1,757 +0,0 @@ -#!/usr/bin/env python3 -""" Test Create or Update Branch """ -import create_or_update_branch as coub -from git import Repo -import os -import pytest -import sys -import time - - -# Set git repo -REPO_PATH = os.getenv("COUB_REPO_PATH", os.getcwd()) -repo = Repo(REPO_PATH) - -# Set git environment -author_name = "github-actions[bot]" -author_email = "41898282+github-actions[bot]@users.noreply.github.com" -committer_name = "GitHub" -committer_email = "noreply@github.com" -repo.git.update_environment( - GIT_AUTHOR_NAME=author_name, - GIT_AUTHOR_EMAIL=author_email, - GIT_COMMITTER_NAME=committer_name, - GIT_COMMITTER_EMAIL=committer_email, -) - -REPO_URL = repo.git.config("--get", "remote.origin.url") - -TRACKED_FILE = "tracked-file.txt" -UNTRACKED_FILE = "untracked-file.txt" - -DEFAULT_BRANCH = "tests/master" -NOT_BASE_BRANCH = "tests/branch-that-is-not-the-base" -NOT_EXIST_BRANCH = "tests/branch-that-does-not-exist" - -COMMIT_MESSAGE = "[create-pull-request] automated change" -BRANCH = "tests/create-pull-request/patch" -BASE = DEFAULT_BRANCH - - -def create_tracked_change(content=None): - if content is None: - content = str(time.time()) - # Create a tracked file change - with open(os.path.join(REPO_PATH, TRACKED_FILE), "w") as f: - f.write(content) - return content - - -def create_untracked_change(content=None): - if content is None: - content = str(time.time()) - # Create an untracked file change - with open(os.path.join(REPO_PATH, UNTRACKED_FILE), "w") as f: - f.write(content) - return content - - -def get_tracked_content(): - # Read the content of the tracked file - with open(os.path.join(REPO_PATH, TRACKED_FILE), "r") as f: - return f.read() - - -def get_untracked_content(): - # Read the content of the untracked file - with open(os.path.join(REPO_PATH, UNTRACKED_FILE), "r") as f: - return f.read() - - -def create_changes(tracked_content=None, untracked_content=None): - tracked_content = create_tracked_change(tracked_content) - untracked_content = create_untracked_change(untracked_content) - return tracked_content, untracked_content - - -def create_commits(number=2, final_tracked_content=None, final_untracked_content=None): - for i in range(number): - commit_number = i + 1 - if commit_number == number: - tracked_content, untracked_content = create_changes( - final_tracked_content, final_untracked_content - ) - else: - tracked_content, untracked_content = create_changes() - repo.git.add("-A") - repo.git.commit(m=f"Commit {commit_number}") - return tracked_content, untracked_content - - -@pytest.fixture(scope="module", autouse=True) -def before_after_all(): - print("Before all tests") - # Check there are no local changes that might be - # destroyed by running these tests - assert not repo.is_dirty(untracked_files=True) - - # Create a new default branch for the test run - repo.remotes.origin.fetch() - repo.git.checkout("master") - repo.git.checkout("HEAD", b=NOT_BASE_BRANCH) - create_tracked_change() - repo.git.add("-A") - repo.git.commit(m="This commit should not appear in pr branches") - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{NOT_BASE_BRANCH}") - # Create a new default branch for the test run - repo.git.checkout("master") - repo.git.checkout("HEAD", b=DEFAULT_BRANCH) - create_tracked_change() - repo.git.add("-A") - repo.git.commit(m="Add file to be a tracked file for tests") - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{DEFAULT_BRANCH}") - - yield - - print("After all tests") - repo.git.checkout("master") - # Delete the "not base branch" created for the test run - repo.git.branch("--delete", "--force", NOT_BASE_BRANCH) - repo.git.push("--delete", "--force", REPO_URL, f"refs/heads/{NOT_BASE_BRANCH}") - # Delete the default branch created for the test run - repo.git.branch("--delete", "--force", DEFAULT_BRANCH) - repo.git.push("--delete", "--force", REPO_URL, f"refs/heads/{DEFAULT_BRANCH}") - - -def before_test(): - print("Before test") - # Checkout the default branch - repo.git.checkout(DEFAULT_BRANCH) - - -def after_test(delete_remote=True): - print("After test") - # Output git log - print(repo.git.log("-5", pretty="oneline")) - # Delete the pull request branch if it exists - repo.git.checkout(DEFAULT_BRANCH) - print(f"Deleting {BRANCH}") - for branch in repo.branches: - if branch.name == BRANCH: - repo.git.branch("--delete", "--force", BRANCH) - break - if delete_remote: - print(f"Deleting origin/{BRANCH}") - for ref in repo.remotes.origin.refs: - if ref.name == f"origin/{BRANCH}": - repo.git.push("--delete", "--force", REPO_URL, f"refs/heads/{BRANCH}") - repo.remotes.origin.fetch("--prune") - break - - -@pytest.fixture(autouse=True) -def before_after_tests(): - before_test() - yield - after_test() - - -# Tests if a branch exists and can be fetched -def coub_fetch_successful(): - assert coub.fetch_successful(repo, REPO_URL, NOT_BASE_BRANCH) - assert not coub.fetch_successful(repo, REPO_URL, NOT_EXIST_BRANCH) - - -# Tests no changes resulting in no new branch being created -def coub_no_changes_on_create(): - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "none" - - -# Tests create and update with a tracked file change -def coub_tracked_changes(): - # Create a tracked file change - tracked_content = create_tracked_change() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create a tracked file change - tracked_content = create_tracked_change() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - - -# Tests create and update with an untracked file change -def coub_untracked_changes(): - # Create an untracked file change - untracked_content = create_untracked_change() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create an untracked file change - untracked_content = create_untracked_change() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_untracked_content() == untracked_content - - -# Tests create and update with identical changes -# The pull request branch will not be updated -def coub_identical_changes(): - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create identical tracked and untracked file changes - create_changes(tracked_content, untracked_content) - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "none" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Tests create and update with commits on the base inbetween -def coub_commits_on_base(): - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create commits on the base - create_commits() - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{DEFAULT_BRANCH}") - repo.remotes.origin.fetch() - - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Tests create and then an update with no changes -# This effectively reverts the branch back to match the base and results in no diff -def coub_changes_no_diff(): - # Save the default branch tracked content - default_tracked_content = get_tracked_content() - - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Running with no update effectively reverts the branch back to match the base - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "updated" - assert result["diff"] == False - assert get_tracked_content() == default_tracked_content - - -# Tests create and update with commits on the base inbetween -# The changes on base effectively revert the branch back to match the base and results in no diff -def coub_commits_on_base_no_diff(): - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create commits on the base - tracked_content, untracked_content = create_commits() - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{DEFAULT_BRANCH}") - repo.remotes.origin.fetch() - - # Create the same tracked and untracked file changes that were made to the base - create_changes(tracked_content, untracked_content) - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "updated" - assert result["diff"] == False - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Tests create and update with commits on the working base (during the workflow) -def coub_commits_on_working_base(): - # Create commits on the working base - tracked_content, untracked_content = create_commits() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create commits on the working base - tracked_content, untracked_content = create_commits() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Tests create and update with changes and commits on the working base (during the workflow) -def coub_changes_and_commits_on_working_base(): - # Create commits on the working base - create_commits() - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create commits on the working base - create_commits() - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Tests create and update with changes and commits on the working base (during the workflow) -# with commits on the base inbetween -def coub_changes_and_commits_on_base_and_working_base(): - # Create commits on the working base - create_commits() - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create commits on the base - create_commits() - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{DEFAULT_BRANCH}") - repo.remotes.origin.fetch() - - # Create commits on the working base - create_commits() - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, None, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Working Base is Not Base (WBNB) -# Tests no changes resulting in no new branch being created -def coub_wbnb_no_changes_on_create(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "none" - - -# Working Base is Not Base (WBNB) -# Tests create and update with a tracked file change -def coub_wbnb_tracked_changes(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create a tracked file change - tracked_content = create_tracked_change() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create a tracked file change - tracked_content = create_tracked_change() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - - -# Working Base is Not Base (WBNB) -# Tests create and update with an untracked file change -def coub_wbnb_untracked_changes(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create an untracked file change - untracked_content = create_untracked_change() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create an untracked file change - untracked_content = create_untracked_change() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_untracked_content() == untracked_content - - -# Working Base is Not Base (WBNB) -# Tests create and update with identical changes -# The pull request branch will not be updated -def coub_wbnb_identical_changes(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create identical tracked and untracked file changes - create_changes(tracked_content, untracked_content) - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "none" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Working Base is Not Base (WBNB) -# Tests create and update with commits on the base inbetween -def coub_wbnb_commits_on_base(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create commits on the base - create_commits() - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{DEFAULT_BRANCH}") - repo.remotes.origin.fetch() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Working Base is Not Base (WBNB) -# Tests create and then an update with no changes -# This effectively reverts the branch back to match the base and results in no diff -def coub_wbnb_changes_no_diff(): - # Save the default branch tracked content - default_tracked_content = get_tracked_content() - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Running with no update effectively reverts the branch back to match the base - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "updated" - assert result["diff"] == False - assert get_tracked_content() == default_tracked_content - - -# Working Base is Not Base (WBNB) -# Tests create and update with commits on the base inbetween -# The changes on base effectively revert the branch back to match the base and results in no diff -# This scenario will cause cherrypick to fail due to an empty commit. -# The commit is empty because the changes now exist on the base. -def coub_wbnb_commits_on_base_no_diff(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create commits on the base - tracked_content, untracked_content = create_commits() - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{DEFAULT_BRANCH}") - repo.remotes.origin.fetch() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create the same tracked and untracked file changes that were made to the base - create_changes(tracked_content, untracked_content) - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "updated" - assert result["diff"] == False - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Working Base is Not Base (WBNB) -# Tests create and update with commits on the working base (during the workflow) -def coub_wbnb_commits_on_working_base(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create commits on the working base - tracked_content, untracked_content = create_commits() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create commits on the working base - tracked_content, untracked_content = create_commits() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Working Base is Not Base (WBNB) -# Tests create and update with changes and commits on the working base (during the workflow) -def coub_wbnb_changes_and_commits_on_working_base(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create commits on the working base - create_commits() - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create commits on the working base - create_commits() - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# Working Base is Not Base (WBNB) -# Tests create and update with changes and commits on the working base (during the workflow) -# with commits on the base inbetween -def coub_wbnb_changes_and_commits_on_base_and_working_base(): - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create commits on the working base - create_commits() - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "created" - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - # Push pull request branch to remote - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{BRANCH}") - repo.remotes.origin.fetch() - - after_test(delete_remote=False) - before_test() - - # Create commits on the base - create_commits() - repo.git.push("--force", REPO_URL, f"HEAD:refs/heads/{DEFAULT_BRANCH}") - repo.remotes.origin.fetch() - - # Set the working base to a branch that is not the pull request base - repo.git.checkout(NOT_BASE_BRANCH) - # Create commits on the working base - create_commits() - # Create tracked and untracked file changes - tracked_content, untracked_content = create_changes() - result = coub.create_or_update_branch(repo, REPO_URL, COMMIT_MESSAGE, BASE, BRANCH) - assert result["action"] == "updated" - assert result["diff"] - assert get_tracked_content() == tracked_content - assert get_untracked_content() == untracked_content - - -# pytest -v -s ~/git/create-pull-request/src - -test_coub_fetch_successful = coub_fetch_successful - -test_coub_no_changes_on_create = coub_no_changes_on_create -test_coub_tracked_changes = coub_tracked_changes -test_coub_untracked_changes = coub_untracked_changes -test_coub_identical_changes = coub_identical_changes -test_coub_commits_on_base = coub_commits_on_base - -test_coub_changes_no_diff = coub_changes_no_diff -test_coub_commits_on_base_no_diff = coub_commits_on_base_no_diff - -test_coub_commits_on_working_base = coub_commits_on_working_base -test_coub_changes_and_commits_on_working_base = coub_changes_and_commits_on_working_base -test_coub_changes_and_commits_on_base_and_working_base = ( - coub_changes_and_commits_on_base_and_working_base -) - -# WBNB -test_coub_wbnb_no_changes_on_create = coub_wbnb_no_changes_on_create -test_coub_wbnb_tracked_changes = coub_wbnb_tracked_changes -test_coub_wbnb_untracked_changes = coub_wbnb_untracked_changes -test_coub_wbnb_identical_changes = coub_wbnb_identical_changes -test_coub_wbnb_commits_on_base = coub_wbnb_commits_on_base - -test_coub_wbnb_changes_no_diff = coub_wbnb_changes_no_diff -test_coub_wbnb_commits_on_base_no_diff = coub_wbnb_commits_on_base_no_diff - -test_coub_wbnb_commits_on_working_base = coub_wbnb_commits_on_working_base -test_coub_wbnb_changes_and_commits_on_working_base = ( - coub_wbnb_changes_and_commits_on_working_base -) -test_coub_wbnb_changes_and_commits_on_base_and_working_base = ( - coub_wbnb_changes_and_commits_on_base_and_working_base -) diff --git a/dist/vendor/Deprecated-1.2.10.tar.gz b/dist/vendor/Deprecated-1.2.10.tar.gz deleted file mode 100644 index 77715a55093ba25af6700bea884a24adbb83b6ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2969723 zcmb4}RZtrYutp(Ra0~A48r%vYxVsd0FAl{@kYK^x-KDq{DDF_aSWD3Yr8u-u0-_meB*F5H#<*Y>$S+n zUbds_;AcE@CbI1Ry1uJtpdwt_!>gJMSa5CUR3pmv*~ToZjIf@MU|Z&wrHMt6 z>+{T+LFVbBB+a2g^NRtAW_4Uwa?`8UORl5wZ?pnF!sG+4k-n!c{1D>7PNtY z31Y@-pj@{b5u|l8TET=gf-&SGHbH=a_nOd4d)EM%z_b^R<$-Bg5IZ`S!aiB{Icgu_ z{t2L~>^oJK7HeWVg;v0gkyYyZVHfwbDsLxm6n7miw-qdUEBq0=eyL^-~-?ZLsw z;Su1H;L$O#g}Z|V-sBN#&$n1x53*icE0@_|RU-B(cDhkuf~{0-9JqCu*!DDvP^fYC zFUBg+br~eZ$;j7_DXG^N&biEH<8w_pZ7z7L`V=_d-dMg&4ZkXUu7K{x7U+6@YHuNV zc^6=4$neU?*CknS&xvvUL2{e&@Ky2$I67M)^}-+{XT|~C)F(`d?|tP2${mPMFU~jW z4JT#_3lRE&r$T6lUW!ybTG{+I4x4Bjs~01PMIpmB!yv^}7fQMxFG;Tul|mJWQ9o7m zkUBG|Dj4-gS^9TXJMbdYXTX91Zwp|?mJwb_`N`V604HWvg@M|%mA1ip%@UH{;9OzT~SNE zOZe!H z5lQBjEd*;qBX_uqZ7)Pg`4+>P&nf9r_2Z-(p#mbIH9`SJhhkumcMzLUhLV`+^6MA; zScV0f%O>)Z?7c;0^6m}_kDCY_)9AH!b=4TOaNrwy%WHup&`0R52OR+E5Rw|AtFEox zl2Sr=tj$ep&i)8$nA;7|*C(Q1VS5jYDU?sKcUvHe9pPoe8!w5pLG`aj!ZAb@5TQtn zbs(sYgly9RG|({sn~2;$iq9%|q9ovpY`Y=sfB9)bH)TsyFqt2f+<4dB;+QhjojB&{ zb0Gxxlmhc=-E66vgC!*a0(STKiG(hh9T9eiSXAG7@u z0(czT%@2~`=rBwqj{b;YS64KAYmE>u!jd00H!U^X9J-&K%&gb5LQA78eZ9;$c9?AC zXo#Dc4tfwB5D0TlxOhy&vO)+>I@)6#k#b7hwHgdbp*~E7I#vN$&d$$t17}*>k5v;% zA9F}7R7ODY5j`|ZZs{`h`@Yvs{oKZ{$Q|pc^0X$S9*?mA zM2{UN!_k?;o`ludd9e%cNmdU@L1cI5=D6aoveu|dS-MP%2U zw2>aw(qOV0gCbG&j1-+@32@I-cF&=&F@q9B-wEj1WfIk%n?I1(XoPbAN#huIPD^O_ z)k*DpsE3X{6KG6&XVw<`- z*311R;jTjs4_$;#;{Rp-q1_iwX_5K^H3e!0rAEbyS1Pq_x9mfj8%ji~G(5%z7Kv$4 zR{8>5Y(j_em~#x8BCqI}enOa(&3GuvX2;2h_H^mvh$H^8)H5rQC&3vC;0)d9K#Ue@ zas-{TCgEeaJ7q5-8W0gRf*xI1Cf>|6O)I{JHVlbYCNeT-=uRQ#YuuPX!B<%N)eSmh zX)vUt-A!1BnBj~Z!DiKUQ=VmSP*ai&SKv_ICq`b!VyNl}jqzC2B)=95*SLojzo3#B zK?@H|1^^;NG*g_Q4Qp)G11};SE!N?nk_{(n2ii5--Y6gwv_y20g;C{u^J|JinMQpZ zgWfpCpR_(p&`9lH8@MI|K8Pu*qHM5|aq^4ujV!jcm14%2|AUq2LH9X#=-4U_GVPFm z`7IGD2Dg5fP#OLd;_bD7s^=}M=z`k4QQ(j4N0v9cH-Zhw=R(RaICJ{ilS1KhPJPqU zRDqyuT@8N2rCh3gZ7KWw?hy=tY}7)NsaZSH{9si@8kZY3mi-n)_5JqV4=wU63)z)q zRz}}B0v|#VJPI~+lm6qc!ED-3hQM~<;*sYZ0NERp$`#rIh(4`M#X!eF!NQ(I?v`cL zT-)G_FvJRsB37T$i+DGg2X+o`vSVuHEmjVsj+I6CChEiN{hNWUn_&eMrbotg*ugMP zwu)WshEORL*nzFh1!T-Dq~Qk#*X*;o>`Ni(rjoF>TO3*Y-~-a)({fP z9%Z;~tV}O?91g-_kVGVOH@2FjFg`b9s>RF%%W*7rp9)Gml8t~3Sw<1ab6kidqq-`m{AZ8%jV z3uSY&`Sxaglst8{=n*C9q|W}l|Ke-@r`{mSZ{HFdX?X6wCBA_?@0>nZM)xzCzw*&_ zyq@Q1IdfQ}L6P=Jw96i~Llt0Vaf#ve4nags-|X* zfpJoG#?V%Jji^7|w4RSt&^+bYLyxBqVk^H!d zJkjwmH`j212rEahFYnYW!Qkz%Vbca5R!LM|Z3Kc*;>|~c`0!~`L6lc$F1DRgtJ*xN z&H??bZpG4igpEUNwiju+8<7`E*Ij&R4$s*yGPPN11CPrjoM+@kz=ISg=oBy9oIztj zaKM6aEeZi)G^4Hl$~LGyDZ_{oY!F+Au9sDz2>J}nhmY9|6`~x_8erzmqmr%5LUZP$ z)H@t|ve`}hol;~!MNI6M#w2Zn2INz`DF5;oqWaa$)`Sb z@VW%NvORoI(o#$K)OM9qG~RSh*M;l0`Wm_Zn)vj&p{&d;vJ zvf_JT7rsTSkaIazn8(pyV^nz5PXP2X+?My`w76$j5JPS0`)E6=oH0;{olCwmMd3#? zn=ttEt{a8p%X3U)$ui?Pv(gR|G*fBg#Y!OyanW<6?+Iu(*HDJv;&n;kstSA2UF%g4CNyKR?JXer_Ai z^?&*AZayKee5JXP3nlN5+IHIVzuE|m78A#G`LvUWW=}S8lVyf>m5L1OhTJ6;O<30ir+{O=*-AU)1w%&mZK%b>myC0Z39BTkSg{!NO~SZ2mwL?i;a;{j#5A* zU4C{5%aO2xN5mvbZxdtpq$n-^dl2?n2q_l>*DeAJ^bmG53pI~M2cYB#Tq4W5Xi*Nc?opr)GZw@ELhW*rOGjhq!m zny%6Q2DRoVTJ;_ElvW$h(Nb@sV_d%{V|-sE7iiNZh0Khlwb+%0op7(@^n}CpMdKss z?*;Hm&qaCrk&~z$qakjRX*N=yhDK|(feIaR*kcZOmD@QH(Yvf{sNr3o4x{iJ*8=tG zN1i`dzrs!K+`&|DHyus)TU$|%cXn$UxR;+l7i2e=c3cMr7&Z_Fa=x;-DIn`n(0xHKGppct!pZ)vpldXB$b0L##iGW5J=5Z^DI2mN%Ki5CD`ETvo_j?<+g~1v*0@{;Do|wJcZ`Xi0q=9l~Z#@OE6Fz$~GCa@7$Dr!=XG5f-*!02%A}lu?lCd z2{9)y`24+;OGfmBEo&ZgU36W{8^ENX@{fH1U-$UG>zD;zDQoSdPJt+rM=?Fjonsbq z4&(>bjYRE)5EO_mYnE-Y5*G1IBkz?h2HNc`@&RFoVF?oLCE-5TUYrcYsg6D~%+Y4k zPPd#+oQ{ptmw7q}a-}cipQDmGwx|rm?>G2^CWKXyL#AqF(GxZ;_+S(B&AMxyi`#yl zs4xhJE-AkVNTe6f>FT4gL@(TI8rXeMEyiiakETS4@i7Q86~Yg?!(te06O(hG=ZY?P zv!|*ZgTG3n0)t&e>+%D@hRSD{(Y{I8se9xuVx>2umgvE<|74w09%M>i0~j^u*qw$h zSc9G9!Cv*U&UDthof_uRp0AyFbilRRyFld zQFfL~x@Gx%Xiw#Ak>7a?_|BhfhecN}o+~BxuNke#aw`d+lvK-v-i~w*0Hck$z7YCI z>Ni46pI6Pak-G98ugGwZo3Kf~2gg0nWx94GK){6@;(QwjHyb=Zw%SCL&2bW1--9DC z7NmcK7}(j!l`XTjn-*&ak9BG~QT!0Rp7RYsAC4wukII6I>sFLRlDHw&1~$%naEzVl z(qA9Q3MIX0%R$1Axd+qb5#-WcSH$^+)jX7h)-Ead3~CB@#QnJJOa@z4S1v1R3EDm6 zS)f+uMF)z;mH`6ijBL<>jK*;b3`cS`S|bX!=k&9gG|x%H{cf?uvGSTr4yig(z&jsq z-~CS=HqLWOgY8b+C1G)>i?gM>o?=k!Q?2$3xdhMirec;o^)EcNKgW%@`(V@_-lAfo zW2YuB9Uj6U)G{1`Ga60Kc{xgsAa3f3DCNRLy1kK+;+Ox*wv?5X4_a%&+4A(UQ0VIQ3 z8lB3J#6Px^j7^Ny0+rBliBU7OBqHEzL?g3?J%7;wbhhe~VaQ@XN%qcsL2PYWhQH@b z5*OSeVHRI9GE6Y}Xt+Y*E2DT8gj1(+Bot9aHJy?zYq7;?nup_z#~BdyO(2MHiJiBm zrB93=tMG9o_Jq_Yh+D1NGHIwu`dG1D)&Z>R5m~@mNo-f27kNCIZ8Af>CYQLc&oIGJ z-;$9z^y+>jwng|)SZbXVpqyXb1Vu~=Ar{jMakZ2sYTXfDc4x$S#$HEx!0ew1UQE@- zs|=i8VTMmvzg_~1){P>>hD*v4(xSef+0k-!pxvwE?|M~_hxh$m#TrhglThkT1u1w@ zCO6xoiB{a==EVQ@4dvW;T(9T8pLRDdrpzX^_hqYWFXZD@MZe%U9Y}mJ{V@V`C09O`qk0XjD03L{Qbz9Kt9q4Q>4h za-(e2qvHke63T<#3REqP{h7>@LcfVjYc@#RA1n_Kk!A+M#6+4ysZ@mFW#L8!O{m+{ zd!(yh(&y4_V7UuU)Lp)W_XZz4)Teu6V?_j+JRY17Ib1P79sX|J6Vtk~<+ zEDuAxlmQIT6DJ;a_cQw(rpBdB0=6|)m@MYfNj}jh)#N*^MrF<$MxM8= z@m?$Od~TcudFa2@sSYm&`(YVyu+`}@kJ>nqG+>>APzs&T3t2`RQXDu{yl_W;r>V|N zUO?X*n#li&Bv&qL%{lUyx4#>|Ctc$4HDbhAcVgDDjU)1Uq8S6yNQ*@xG0&9|*Mn4` z#DeS?^pq~X2%NOQWcxzxwQ7?^WCRIVFCl%pBX>Eyp@atIHeKd+8yBf5I?b?NkyTTX z)t|tVdP|j6QwZ0NK2fJM4OuG{he+V_U_r6a=<4I%!ap0n9S8dj1yp7C(%dF`R~LDK zxWxrA?%pD$wBtruI^yJ~hC7%eB`pD^Qzj#M9s_PKFp1J>iM|sc84z6_W|Tz%K)q$d zX;sgaKv^YKS{0c^A}N+GT6^p~sv2+ds0YCeWW6wZP};h!jaVo@D$xqyaJe~qIJy0D zfwl!%=N)4Dg|3Rf{ncRpo4aPOM>|F{Wo~g2f{Ox!MOwU|fH#Z-`AFs4{V=Z66D&dstg_x?)L`bJB2jt$qp;Lk3}s$5jBf1J z@dsa)7Aq4x!B4qK3Rb$ESEZH~ zzOQ}Tkm|4g)RWl##_H9tG_F~2qcRsEMT@OUznC)(v&BRlM;9haqc>HLD(Kvopw~pN zEC!OZEI-9Nnmy}GeavgwKrSX%3tUx=Edsr%XipDU*Q2yv?VmE{!%Yu=p=TDwt-?_* zaRd;%oacS7QiTRWv2SPUGRRG*tto~VoeosJVYk>qpQ6KQ4>oyI(_1R>hbv7V-{b7E z*GnyZBV?@mUiyd3ZqFfFy@F>)+ZK1 z)rA@plC2tc3kCnIX?LQrJLI-R=6^Ca1dbi$5A>M9N7&A^k&rvogl@r9V6ks$zDgq@ zsYeEX(k)sY3?)g()+=X;*k4ZWs``H0*Puq)f zT;+Yr<8Y;Ns^d;NBW78^sYg7##$2OHjeM4MT;VWZK$z^%q9IPRcGh})0`Z0(wN8Wi zl~aR0mPay)Uer6H#d#tgrjC)EfdnTwtR^}{t#c`cf}&7Aiw+RF&>UtksFZZ$HgddzMbuy5^ zSD>H;x>Fb3u*Juwc-su_)Q*#^0%!k`t8exMc7~(q?q+929IKdZ>&Qqf{grjZ-qyN! z%@&b<)A4GVJ7Qv(TJ-u=hVr$=R%T@Mp}|7KD zhd_dfriJ>A)!M$^Di7UF@V=u zbzFnO-b42+iEMqAfEB^ljhr%NTx577eYmrbGJv@)OB#J8vY8U+w;Cq={0k5c*MLun zjy6wR=LnS3CMs5(XF!XmVtv;HBGIJM6^6&qJWsDp!RX8>CHvZGiKrD|ZCdA_U9>tl zDYyb-r1Z48yTl~;vnFLR$U1se(^j&K9-5ovQ3M`WDl1O<_;2$bq2m>eDyKcCwD-4o z(Y&V3;!7-w6r4h@MS#K?NREDmu47!FkTNnUnN}HX=^yB%eq-ArL8?=KT#1RsA)Hq_ zkP;U}8?(VC@Y{uy&-RpD&;{qh@oL9#fTYbPl|YAbgKybb*GArMw<5^M)1Y^Mw0lOd zGf;w3vQFBAQY7ve0ee~bkVdnFf{huMN^gZP5VyPTYcXuA{EQ@k71hGDq8}NT7Quii z9VB}Kh0D5;jaG~mX52IAqmfg@W4Tb$QclWdD07ZEuSr-r&=-_qm!jcPL(z$^vXXZC zFx(NxX8>ksg*)L5();baDRddRx!);W#yK-ohHXS_xr_h|zJyMTNLfdNNk2lJ<_`NI z6&4S$>~q~eVvT>$n8hfE41E+{Sf**#fg&KTS!)h)FcicOF&2$Z%dcjLq76UKI7N=q zq#lG!AutE8Lr6;lS|lRX+|Z?Qv7A;z!%#3pX)OqhxC^Pu8aKjy(BODf~bakzRe%9vAmBR?eVGhr4;F@oW* zE9gS_AB=gLqhEOR(HJ_gAc60~!(Q>kN8)U@!Rl!ZGRDoCQ#Iu<;BMuc)fZGP7ObtY ziLoFRuUcI|S2-sqvZq=O=Z;My?I==+FLC^sh{VJU)>RhDE{b01XvX2;&`uRI8<8*O zP-ZM?vgs8mn>XoOlmkR9Ec5p&A^}N9gSJ2>gtnwH(dfU1%^|_05SN^-IA1!h!S4|< zvXeZisZ~BuT>IL8;3dr}R9O^E;2#5@L4tDbBKp|1l1!i#o|3TB{#6B<(H0|{EbUF8 z>LoB@ofX*jA4}C)@KGqLk`>i+&`d8~U{V8Ll%_Ya){ay~>P!#&pJk;DY_vW#JRdiy zw^BadS@k`nlD`(;8^pC}q!qr>P~`-6TEj@s6qeau zH#&Y6Yha3ORrIbz-O?X(k@8vT(DN#XB@o%i7H@6BP{Zv@xWwizGbN0`5v8N@KjA{j zYL&Ku>Iehk8T{X-ovApH)GOQF;ZMfP!!Db$!!ku;*?FZ|=@Rv{e8va;`oB*z-3P6Va?@rV z%Y zB)JxyZE?4p;K{$OU%y@$ zk6A55AX9YGy?dow{AYQoUFmlF%=aq(Ysc$WUCrmM-ajqxmwoP!-c^ksa?4x2Z=W2M zLQG9;SQ8!rvMC-j-JQ4G=9_x=GLucHHO5yJYMFM)vq1%=EQ)DMI5Xixt866>+hbio%(8>_m4NmDf6>-|qz={;jBg~qLXz{$LtK5j z@=mvwmN)iP@n4oAg8VqAY7?peW!APw)_5G1bqup^Id|@7sE+Wkwevk;Y}2e8X`c6n zRbG~%8I2OLqKOge2s-Ij4~pA^M>{~dN{BETPIKKC^2oRgG^-praEU8Ls4%du7!gD( zRuL0u`pX>hCiDh_mOi>{%~(*4p+2(+%|$#-Q1wU5GIg-FLlfw zlH3hRbr)hEvOfwV-t5;3_a~D$4D{N?cK(vvGQg}&C?Gmyt~|?Jyrt)mXXJCz=-*HZ zRgTvPRb(A+g=7TRXQW;0GttdHr%-V3?omy~Wi4Lmvt8TVUMk@IDql88>%m*gSc~t1 zV6Y5MAl%}kRb1b34i>y|t`Y3Z{2F5-d}b}UqA4HOj(o@*(TF>iE1uylCu`8ZQs&nV z{qffE)I{5x^x9yLI^6IC#x6c@PeFx)ESDomE&WMYe6V2#U7fl_27k1sL~EMRRGvFn z+6&tVfAKDmM7SICh)4QTWgfzn^FuyVjYxuL;n2U0eC~IbX!B(|LuYKGks!KDVjpF~ z(dK5Bo!jW-Ab7p22#lNsp`L8TuVvX@j5RKZ)*&MysdddI3P2v)UF4UXh6|rH!OO$0 z*NRIY>v5n;OP1_1h!=+)GM_&NAI$MF!6>jg4oi!UJ&{aUaOvQpaEUEjNo?!M6GOQiSY?O>#6n0a{oX{MAOx&WACQNG#YPmd_pTcIz=IXnk(!_^z)mC?~vyw zbEa{t{jjw8$W|2F8CSb>-j&qf8wU$+2=5AcG`Agise`WFd?{pc7bjC-lMu(yzJrNY zfN`P|k;}Nsuap=aL*1nb8KLnJp`?hw-wh@?&~HjNsR4m!DB2{i53I08gd{46o}W0f z5Gvytwtv4_(Udrk38kFfhRNQReRNr44_C*Qr^NAQhxcU^*g4T7ItiBuUDi^3P+SUV z6NxbJgt1}(wq8UG{^*>dRZrL@Xl8<7ypw`8H#wJk-v-^7irla4js7bdl^quVL+oAt@;R=>0J zcm8ej)YZb>HfJ4o-{gQ;uITw;HfmZeqglH|tEY9@o5tU0ZAxZpfX}HHj4}e?VNkcw z+%6k%`dUdTs-zA2NX^9au94Cj_owpA+ZiRZa+^_MP9-xYzwK{}IR_&c=8NHi;g3ax z_~yJ0b)&=%G@4u+AiJjY@r$V}yezi9rYzK28nc8)FOGh8JwEEw=w(wEp;S}yf6cyZ zwq*%MqjF;+PH{6>6BY!lZz->STPgcKZ@-q`d~Uignum|`)(h6S{kft0)V6K%9|_uT zHWE|%^1**}!X@@s+ao}3UR9dDwp!FNBs*bujKEAaEs$5*4grSx_`p3qHT?v4C8&Nm zw(o6?irFek@P7T}sLTmGE6f8$jHD=WFnXPCO;c_<3iWQ~Z!ct0NaKD3ivLXD?rH4b zLr|UKWNcx<>_VF+AfHq^7YfjrbjARTFa=V8%^HAPS6md8h0-Tof2<-(ZprhL^)RT5 zs``uP+c}f0AfvCcaUY^ZGh&0Mywg68E{>BDTjl#@Z!}`t+N6Mk9Dwv;F3}s(()q#T z#Dl_(EYC&f`dJpR>5$xjxaYho@~My-r&hIbc~Yl5ubmWB;r-maVv+qJ*^g0t9K$_R zfk#!8U2|Me#!E3$OovcJtvSzeMMfJcrZ1ag1^>ekcVXv4RLU0`(rD$!*{V0yBQqAt z`Qe^TM3^SN__(Tt>~BBQ5YwfXY!@g@!}X%XBzn3`7p$oiQ>}-+H{m*VInC4VBkY1w z#_H_>|1tt671Jp`Ij@~HxQf_G3!jVvU0f_{<}B(}3ON#=;NORKYInBL4U2yvqZR)X z7&`ji|GJu0 zYRRW$Q@hwZOo1c6JT1mat>v>o#OqR{;}dwb{1@W53rKPxEi@eB<;GonamI7CznAdq zxHV665tgsisk)_8eB}_S{QdbgyYk^ z=xvs{kd(=#O@wA~=YS9o^2g8GMwSNm%I73CY{WBrir#;K@ZBG8ar=&i8Uy-gJXiI%}z9%WMq+zDO}qpB>8>8Xot!q2l{A`g!uj^^ShINSe?`_xzJl`H=9i8_$G}ZQe!nGFZ2)MorQ3`bo@R8S23uW6` zT;5pxz6zZCg4FCj=dMw>pla)C`?ib3G&(qB-|g>kz+Bxs=b@_ZN8001w)^CFP8T^_ z8&W=oqHpT^?G>4}3%&!T>x;iHDd$JX3Ae9^cI7=#+%?{TsZ<*M!a!&+d zX$lv&GHRoK{^Kj`g7iRqXABx34n*4tT6x<%TW9 z)ak!=VrODrggK(*$3Mc~C(Uh(|E$Zq{9lYJQ8_5M z5;WD-AL8#_<9t&lS3-`mny)G`Nb`OR6OO3Ioe}^!`_^tt3A|8%q)xr+Z zUJG9gtJoW!ggMWkF<~i}WEj84)=){1+BQN33a~%^4b166{X3@icchgh0k3>r#bg>W z{bBI+gIQB{>dhHr&@9Um4^@SO?nC+Ud6Zy{cm4uYZ@pMUpE+vITTYv;V-;aik9N;CtE?CBXg30 z-+ix($a>qj+1D&=v@B_l(ql_f4tcV@KU@MI1qV%gO|o!4d&hlmDp=!PS@d2=ai@c_ zXsDM)yUVbwSO0yIQ{vX9Ny8XpD&gx;m14*`fR9)moT^8jzD-GgfUvIr_a9A%L8Vma@9P%u{Ddlb4X1#=$luzZFH4|u zP`6L_r;%T$!wAA%zLR3dB9p#jXQ=9+Bty>`p&STYR(c=ID~?FoCV!TFO!t1uZZ#Z9 z_b|~))^3!#b!vv92o(5?G68WqIREox%LcSF2h!tF%;gmGk+Me+$-Ss+r>Sv~ssR~= znJThXh_a0t-Zm4gSmBQLl|i7YT4Ia~u!!PKR~Y)Z7rNNCA%2Z+lE);!?)S(_KMN~I zUHJYmVSwADUL(^oqJ2arR+U2T^!N^aOa6u1ef)>!X-Oo}`$TUBVItDHi)bUu49y** zD%HinuV1MW9mMHMRf@xAmq_aUr>Q4WwwhbROKt}(98$4vu|LA$QO7#Mv}oPk?;8Qy z?X#jQ0rO55E??umm$=_egj(y?MMW8V-Yh+#v>Mtplt%T(ruDL6GCUd@gv)^37G80|Wpg@mc7;UW^P|Gz7WxA-F5C(>me;p8WI#YW`_{(U zlLlY?b$15SWg@ajOhTbXBCzO3dF{O=MviH%cV}lF?_6o|+FRqVT|V)QyO{F-(iUQ@ zy;&p2mu--YYv0yIsEWqZ0t0F!vWBLwQ@{Ec z+SNw}#MGtNH#V-+&ze?yA4`aDQTAG_iTmP7lZpTIej#yVUWSxtB_AKhl6!_$6SIXNqSGvcjVWa-fH<&P>MJ9-Bm3qRJPO0Hu4 zC24{>PnMUaLOLbxS8t(w+zV6R27%UDiAwr?J`dMF!@uPo!`7@M+r4nu9f3vZESJ2h0N0FNp{>MhUIX@BII{e2d8QhMD8=)~u z!a*NCto#<~s{X4&(H!65i~GONasl6x?mrXuzjidV0&ZRt2VU=X`d;8TMQ@y+91ZfG zel{CPDD8jtPkD0W=qT}4qgEtR9n?(>=!UEdw|2*UbqEQA=n34z^7m|Fq@)t$eryq0 z^GOWPluZWz_wEjK)Tj*Gj9;qVJ=o&A-?Fh$AGaix%xGVIzil|*SXJu%>A`d$rA($h z>s)Fg&DOC6{`BSagNa_`Yt&=$NSwe9=X18?)W6SM)Bok`%ht(f7{lkG+;GQvR1y28o>3h+YC1W{K+^@OPzp6M6dTP>mhreC`01~Y~@M+Jb^GKGHIQi|rO z9E#HPBb_>fci}=5D7kvib%q9?Cvw1O)g*&`LG(f6>2+mW>dU1kbnRV5nw;&qRg2vGkO(qLzF251yB!$8wJ`kWuRq3uO_~lw&u-bngWZc1^ z-8fH^Y@_*M(H%*9M)DZk`go!>Dpw2yuc(KMjPJWpYxyf{ZbpW8GU8BdFVv>g6dr)G zFFOYRNT$(DLB1Il_oMuU;!N!=92QW=V1_fwb)_L-=-M-6`wA^xH9%tGU3&npT6-kA zBJ*8X4vT<=x?@79E1;5|(n#YlI$D3%U`n+ldSRy(q@#TKr+h*J4*6j%D@3H4wY0%X z>+IsytX@f{fiIk4oNWw`r+%N|@LJ*F#X^zQ*X& zq*E&b{Q=EHWGy#ipM_(IYn&yT_RWGtDwyOpbXNESj;0SY4`I3(J3V^d1M(tJuFy|= zuRMgIRfOxZI|E3-WyS93$=n$zuVYzE>s3-_Pg%X^J&IBhCsgYsHmk}}4dIZpZk!V8 z(|pc5O-+h{hR1VEJsr|ZD%oP&uQ3V=_HV#uS7XHN-4|nXgaL@G5t9~G!4pS;$RZ{i z97p*~H7Mm+dK5IC9(D$BND{ZK#I6YWIa*xk- zSZ%5`rq>I>iUl-inL1%&BUMYX;Qlx#8p%;#sE(L;)(co69a$h@+>YcdR%JAP%Mt+; zAinGe+}yD-Pm^`7(XD=Wc6axP+@ZPqhTDb(u7;J#u9;XR>zXziRk{{&66LMKqW{Ig zi6`vhDX>TDD(96@-c|rricQ$dMzNht*wL64yJL+YPO{3=foR4&%n&S#rOQ|dqaBGN zESkhYy=@{=8P^w2VboJyC9ighI?QQ+d+h_YiZPTyA#J3NJQJ%?4P@TOmcV-Cb;JF@ z3dXKvKA$ac$s9C;HmMi8|K`Z1bYyS=H)Z{B&eAN?#dXcAW_vFZ>`N*nn}Io8BRmC8 zzn89cs`mbRcFib+;(}F~d@RfS_G|lEqsjYtFWZ{KL`kR%A<3QVLq;Ke2f>&XyF8yR zolBc`y`KtSO04~)kArUGXkE)1QQ0ybo0bZcn|#UmAA zb870zTv{K?{ihW!x$6!MD!J!sAjh=cgSLH((5Qk;TM+%~&nd6&7UW*(9$f-sJ*w8Z zK|{1{LX}Q+))^uarwq?!)WS1e3lD91RC0&GFHzEhI{vOGs;N>R4!XUEC{?X!baiQT zq2C-fe7hme9=Sfh7+Eqa3HpUiIEhaXPEt%`6Taj^VuHN}Q}NeWn=1XBpzKouKHY1Tr zsn|#J<;w0;bf-Jj-V5q6a%Hr1;E!p+hj_K;;a-`@0_55l7}NHsg>3-#A+nKVie7U3 zz2c<-DdbAFi<=lH7Id z6HX9S9=Q5Eo#kyz6xkR*ccfq{VA!p>a?Qb*6ihYQ=>KY`F^q5pB2Q+;Kgb_#>(n#Y z*bNs(2r2{qDyQX)Jw^R^WK{o81_A++$PfgT$kDsHBxW3oLrm_S#Q|%9Jjjnn8Xyj1e#B7a{NyyP90p zVE`8lZ7YC$M5Wr#?w(nIX)Y#{G%09|b(VJa-gZvd7h zG%)RsYF&gvmlzZ;S2(D&At3`%4TBMrn0%p<7g{~=&Cc95y)D;o`pzE529ZO%yv|Z$ zsw5!c8#wwxSLmEF`b}!CYR-XG5vv+)56#KMMsir5f+O5g#9+%BwrWl{%9eo!q)N9l zDCQXtzB$9zCSU%Nh|6D#D)2E@Fry63skPLgoe`D$llhV9puJGcG)fuXk&8B!5PCHx zkv6O1r}Rj_ALcD$(w&AgSs4{btMx7p%$ph+`w0oh8ilo2=)q|%1wo%CXYu7s$J>x; zWVtCL;kRr^OcS**|7&yCDE$HjYJDDwT(Fc|;uO-bXIb)LH#b!?>zh;EP*t_ruAv1( zmlyt1o)Q(qv4%NQhEOcs%=Yf2!Mecux4S=xl<+?sKXvqYods>zOZJ$C?+fTU9Y0KV)qcmcJBBj=zG( z{-pnvt*TaCU8>ph()pcIRP3`5CC4pcs`yU6*C;i{T(kXe+5kbSsvnzHhC$9nb%I_Z z3G+(+AJ~(8cVwO%9-3ApOVk1QQYr3NdG4R)d8%}{j!>tp(&b7w9#mZlM7mHHe?fEW z3-m&Ull|(@c9ansV79p?;O7^QR4209aI&T{wT*M+2#=ZD1T3`*aFtB#Pv<0rJ)cp3 zuA(hWH&s^~SzzJIGdaHMInAC(x|~0a!Z{~Nn^$* zv+N1zpR7!VWaViIQU_34pwR!4w+Ta{=m``TVV8W7>u_MDd?5}D%|9_q)Kf@X$XC_tOEg0wIn#&mFb8!q9QLmw zf#;GGstWqTz~Qrio79KIvHjZba--Tid$`Xy`(uoOmkTC%DRCm0g|FNrwEGbJQMjc7=^R!=R@Fzi+L95Wsnb6gz`) z5`D^=(+GWP6f@cd#SS=qL&My6p1L?}3Ab|FV>NfeDrwoJny3N~RG50Cbfg47`J7?8 z=yFKrI@vOMxFns8RB~EfK~kep8GnYS!Xj^63HJyg*Qiq0=zNywK~8m4yo!q8O@aXYCNNVkI5)NGi9`eFf@0aKgV{bwOM+z-QNl^34I;`9FycYgl=d9B%4lWZy!KBbE8CzPpxg zr{c6#LD6o-GB?fkpKbmYh+t*?0ZUU!sg*6l_ zDNc~%A2n6s(Q2ahN1OcO@CxBdhY3RAwu9Q^*K}fG_jh*F%bmpjo5wHZvHz;+<>9ig z`%z+obf2wLiig6QQB?Tkedy4yXbO+=8QbJ~^ijw^+E>sJns`L2M7EEi8;hAmY}a+{ zy@4@LP1e92$k*@NWS>yiVtyYJS7^cN(kWSYmGaR#vsJ8u^H3D$V-o!V<$MT#Ix)}G zd4n9XdCyQM-N4|uRD1_$IEvThU@J%E;*{5Eh=Z|^01~nKW?(h{E1vbM&@z({TDfM7ckzW1evyXK zC<4iwr6iysNuc$q4LFTSCegn2?EePWWP_K8M7!uBQ<&B?-$ z`a%s`!2ZMjJ*PLRnmBL| z>H5b6^aw4pTNlQ};7`K;%j|^ZSEcfQhaJ&il>hI5&z4uVylt9vR8w=4DK9V2GzNrzr3;J@73@# znO)xiKgFy}KKwYK?w;`X4*1z4U%xM%HHKXO0e%jdVlsic8jaB3d}DhTKcjhOb9a3U z-`P05v4uaj%Y+>zHPpWj5F1?fYL~;oJDjd^hs#l6I>@x_G};drG;$5Qo(|WAztr0< zV%HavU*k<?+VDs`{7psyFLkije%WlWdAeQdWM z?q3G&9tqbs!S&^EJqh~**H>V>(7;!4eI;w_tDl=pOX13a{ev^3;><9x5+f&$O3{rH^Br4V^`s-|oZJV$ zc0Y2w={vYy2iHGi_tzdw;T})$qJZ?B;fRr^oV?}a0&*9wx7cCreg@B1m|CFF1fJf- zk5-;tLp^rC$|T$~X@8T6zJqcG8Oi1?D+qTmk={;#e^;7x7_@yX(L=7jW^Je?hT$UgVk2Ur5kS>v4;1I98I5vP|AbrYv_~ATqk)LO};7LPm zKMumwVsh=g^Aro-5H66uj9tHG%|w;F424f-e>?U}B{B7Y0L#ZL z&;MUG&Ey&8!iWoh|J|K$;ZOQ{81IkCao;q;`vp1573ApiNba9X{-u6icxIROX{`VB zXZfLjyL8k{H~JabXZGk6jDAKx|B;`@CQDaYwWXpW9OeTyr?tXTVXfqwyG90u%O9P| z(a*p6b1mp>F;fSKVdLSSeK(%NpT|t+z(4)>W7@xSpw9Q-ZUMC_ub=?*%TvDBVV#mc zfr$C2F%4m_fsZP@gYK|h2&%Sd#!(a-4T|L^BXri4+u8?*D|=}PHt zhHHFgW{O^3zTv*%dQ5(*LaUbFb*z4Wcf<8=;|z6~Es^wRyy3p#diM#2x`ylh(-hDx zTRQes70;bbrTJ(|h@wr{6xywhLmN)HX>XHnx5^AZm9eHv&@eZqJMVZ>>#up|5<|r6 z`QMoMyo2-RnqD)VoOg2GEvB4Hb1s^WXscex97k8^NY5;p7)FVjy)gW@?GAs z`SX94Zz|3&%8!G$$<_469LODu$mD_$dT>I4G?|F+3?HKT}Op z$n(j>7OZ~o3H^5{Ks(5EApAbWbU+G>`kd|8nr51gGPRnHhM!sR&1FhAP_~-dO~=4b zhp8Fh91a*}gF5=>7*iMg>x6%^Om(DwooR;2nF6CJXZy22+Q1g@_e_9ZMQqZ>PbYzY z4E&pAIs$0597bAecs>XI^_aS$+)UFnsP8mYLN6>SFf2LSx0|f+&juwdFslc{>`hKL zL6UzqC{+yWb0ARtUMXwjfPZBKP7$om{-*ul=Rhd)pJwvQ^<=8)I#W&lhvNr!+sS-> z!3)IpZ~Q2xkMnvbJUp2%-$l7&XIH@irqmOeo$_8RsGbx*>=zA{=X|=)lVf8bvC!dMx4JLWFuXfw~!^2yym_)nR^hBO%zZ3IJZw;DEcf8D~ z$3Q__4l?E84`u!@=Rc6QG4G!IU*w&D2Lkk;X|8FpX*odS;h)JQn9eZW!oKC1{Nz+| z3vk&j4xQwSA?^NLI}(XRuxvwX72 zb=Fi9TaW5(K{b;C=HG%lvg!kK+!Wmh#ycg|2ZqX1sopDF-q~p!OG6Wpt%5)56|KH# z*fuD{Y-Luv%{1+ZL43QssPJAfC`D?E{{Haqi+IUjTQsMl)!rIw5PPLri{fI}qPA|| zqCQ`ZzvzfMZrY%0FdPeuiog$sLlN0ESX)GZyWkpc+lru2+#hgt&S+vq;9G5xAtla$ zlSI0d)zsA3><*j5VSy4BIT=xeK}$rQ0uVT!z?eZ&RmF&JCxs;rN;<3QjW@NDbF-D4o2{gNuO}iYb-$M^q*e%u*y+*ATV97tycwE&aJxvmqLe#YGvtAL@?kXq-vHc-akB z*;wR1Y_b{$V^KK~r?XLJtF-g7=(Dm)DG#+OP4q3|bpcz2S)EYzUIyHbcr+Ln!gXyJ z#1%r1TKt*@UoE87ZtiODiix7XllbMz_<)j0mv{pCLcfKix^laHnvGqPQZ_>|)=U;? zYA2-tb6lyzYt4(rVRe*gebmcjpcqgAFccwFm&G3|4b`-w89-*h14UXS`iB8UFPnmY zBx+o4h(-cZFcH_NGRK_F@bEO&jm(O(=>OC(}Dy2qnb2O0(V0H_qmZ z0h!7PGLOtV*q(S|$V0rb~iMAK7X3G#t~P>r7FkQFX}m z>N*7MoW?zkk95or334xw(-afpvWUrBYm1Pw(9ylfFmI%wp&kb4wuq6S(py&nqvOLW z1sI>C@bY+DR1xc{?T%{Ro5b+TL`2IDC@6w~$Cdv%(@``_#Vq(s=Bh&)REbReZgeR#POG7)fd)cRKrF#0*2$eS zr)$`&-PKA$Z83E04Co4Zk9eK4y1JSbPk)qJXRiLhQBmVC)|s274q4cakPs1#EWNzk zS#5S|+fepGSzydffl*#zuBoiafH8My7`gX`oMrU+B`*-@6afe0uy#5#_rb2F&UR{< z3<4#jRG(0y7`sC5q)})ptAa(d+%FP*c@ zE)AY_eev_}ou4>wC-M82?%#V_$;F+kZaw?N!&kOEwf3F^|8(EfTkHo^d24POe|det z+WO9AHSevyCARB+pDYgEH+9+izB`{NIpX}}%ENE@=Ke>d;}_Q5w)W2-CYIXH@U8gv zy7QJz-thg=A8_*IK-J2Rrab$%riXvA?03^Y*k#4r-!9m!L|0yXK=n&+g%2)2uKmEL z%--60(i(j7E{cXXRuRr+chx2cWPdWFO-@0f2w))w!YZmTx zwEP=!|K0BFTz68-?6tH1*>Lry0}oqmyY;#{CE51pd7Heqe)>WA#P%E4c2qClbkS4M z`=>wo=X1;VfA5qB2BuGKePHJ)8+UT8`^37J zmcJG`u<^3cC2Jn_N&8-=+`R6^)_wOm@cEh-&s||_``JIfxogp>Pn5eBp8xWqjjz{S z!QD1esW^ zL<7?ozIWNOvkvxud)Et(9JlI}`{u4X%3rq9bky`K+H1ZzyuI_prpfzGSUjiZs`dqi z2Tecni+!pGPvBPUBp)c1_1-to9|=C0d}mzM9q;XX#iHWPH|5!`dvkxsxeLE;`KE2+ z8}mOn^Iy^RGml=7nA7QP`{1BAqsO{kPuj0*Imwh?~R+!{Lr)E?Sl@VbHl)_RX4x1 zvA*ZC%H?Y|-?nFE-OBY}ys>HSyqb9?ne!ie*xG1eRT?fZooSQm7xxaT}&BbqA_wBmr zbFVso>}ucaldXMkKhf|=e|Y_>)6X5Ke=oeD@~X!oXWw|z>+%g>K2k5=dj3a?D|W6v zA@Az@Uu=A#P3}5ce(Y7>r0*-vzUJ0}>o+}dwDXy3Z~tfHc&qc0TUw7-~y81gF-Mq{B6OLMY*0kT=vrozC3-(Mb9lZVB-#@?hw5Lxx zu4ep;O;0Rpz2(r)W=*|r>F0mG@UcMra(UJ7D}s0Uynnd-i2Wb^LR`CgpsV%P=Z-l1 zuOAG&{NkoZDy}(XWAeI+Pa>W8lHR?!N!mpC0@`YvA__ z7TmXa`HW9j9rF15-@Lm2%MZW4-&K`AUsk{V$d4y|b63gSDNkMb)d`Ou_m|rTj%eJp z;lVr3JALP;zT9Q(IMXHPS=RjN+BvUP-L_Wv+trKaFW-0a~Mx@7hZ%FO;WG`n+WS-HTs)rMmWyXW#JW(qBGu&lhz^KeJ%d$%*-=Pkq8w%>^gz zyzuVXGZXtPJfirY&0qYs^Tbs*zwZC&mQ%}*z@;GO3~7{_r31AjcxDu&-uuDK z>ippN4_CZxe*gT_K5n?^q~yP%D_`6D3dbtnCw0r8E4=;WmEM|HX56&+%0Eqd>6MmO z4osYP=3%FQUpRNL|Gqu_V?EbCd3pTrt@q!0@3akl$1QuR$Gc|Z!w;Q#@t^N#i!HN_ ztGWGee;%6%ymNHt<+slGywcKj-+AZW{i~YGk~e*`-z(SHAFAqG_2T!7YF-UKvTFTH z?S-%HabKl(-CZ}eUSD(m-DB76_RG_5I&S8aKI>iYOmFK}chUT}g5y^o-{h*jsQb=w;^O+4`ItDisdpO?*Cx$LmBV!`m=epqoq>*3dL@_*^6SiNTImotx< zc=z>z?pr)>ef-)QtCBRC7POvw_mK_DcA2p5)o13teABTn9s1j;?^j)V*`J^P@U}PK zd3MI%R($jB)t~J;P_oo<(4v2x9Bpn{e)%8gRh@A3iiNEuo1a;ER@a<)yBwO=v+CR% z*X^?E>c1S^_04PFyX$Yg?sm(XwaX^m_xQrVAhBPzjNKu z9}J$e@!sF;|NMK^dmXs8dEH-~54^QGT%x?Rc5qI`d9CL@u*KAH+$B$}JM&g~!t(Xs z{B6TwXWp<+bK@fG~-eaiyXhn`io*Ch>aK5*?G|Jr+H$6t=U zp!%y*q!SzFy;S=94JB8t{^XjuuT&4rX=u6h=5^0JeZ23u+cx_0UcdPKl}k$Q-!m`& z@CiO=a`z8@QC;<*_4VDV%GaFz`7?VT_tEA>_nso3zWLhV-#^*unM2}FY*_s3uO2A- zJ{X+$>g0Xqjr;bnrK=|tH(c}Ob1QZ^V%?!@zdY#Uw#D}A*Z--#ti`{}OV3YVdckqw z>Q%+v-#sEOzwnti{xE+1(UYdEzICJW*4>BPyt>$bAm8%hqI|3^1%Ee zP*z>?=xLsVKYDcftKXcq$CJ0;)>Tw~)#bl(oqg0XCmz}Kl5)kgb4rds@mK!&Ym^s% zch18-e?4vUix0JZd8ab#okNoL=Z-pQ*_(&oHqjN>P&v-NvvmGNkP%@yrb$?sVDNk5#EpY;em6Sp<_{jPb?v_L%O&miz5DZ1r&yvbEq_~l zT;IZn4w*1%pC^y({oO+Yjx(NHQ}Ov13+k>&-t@q$$9}ocUwU0Bp!KG+Kf3$3zZvu4 zz0WsI_jZeIP?Eq^$AX2*vw&YU>+#p&y9moIh)U;T|( z@3?aM*?X<~`3>GHPU8v=D4u`oou66b_uU$uwAA#cmHS+L%Bi>Cc#|?|Q|;VW&Rn@i z;)JDL1Mhx)*}I?K_`78nty$uq`|v%2yMN9S=bLvq z_x#|*2UkzL<*~k_mOZlO^GBuxmcKCdkk9V8d*NO;ebBIW{)at}n*Fz(-`+9y&>L^r zspyMc`vy;0y5G7FZP-23AG_yzgZkAC{O>5p?RTE6tS+9zLL@=nG6E8aOj z_Q*kvpFF?nm1#9g+8=Iv)898Qbk)_@T>s(W&ed!0y?OKE*}T`j6@7Qb8>FW~yjW--zc;dSkpLOLi?ayEF#{=iu8jpX?F9$1bbo8Hn z$2pS+j(zLZinBlIzPQ~bf3#@o#@S=Wy#MQ|P4`}K^Qy}#Zja?3RrpTp{Em*+F|$7| z{%*}P*Zsmht}QyZGUXfyShK#?~yZJXj#xS zZgcyg@3fR%a=^ijD{5|kJpYxon^$hQd)dZYcK@W}kl#*T|L&wG*WO|-zpmky4v5Lc>CL@er5mR+>f{e*1u?4`%L%1&)&Q8<-3mEcP~@- zG5fWZR9rfRpS<*$nz_?fJ@(oEF1_Mw^1!+N0N_u0!D5WJvOLuH^ZAg2i zrMosdMuRkrxTr9RZPb{63{hchBUC~KR{I&2Cp6lo-VJa zthO)v8~eTKO>l+!Y16-wIV3;o)p_QZ&m8qO2$RBO5@&rCRbCLE^Qw7S(=V$wH+h>w zE$Xv8$JM-f*$%DU(7^I%(f>-5+-U#$C4@BBn|y@yIRzM9*nYj%;(p_ON}y<7)rsds z;g5#;^992B$16X_^A}yR5zXtu;av@(zGUx5@JL0c)9DdvOtKqWP_s}JBoLu~lK{EX z0dq7-sANV4jV$d{?1^TNEV2c%1q5%+Ih)O72J;bbR$8(735T=Yq3H-^dkh*8$)o|$ zbF|Zub56nTEN0_barc8E&sgf)<);ZE#^vX~{qMgrwd5X>^U%(+JM{4sUc7PCJ66jF z(BDa(Hf;g7c;CkuRY!FwlDiEH_G)?$10A*LAvR%>I*Jm-hz%8P7e-wZT?x5Y>s&W6 zn{T2bZ-bw^M&F+oxTeF(g)P%bR?K~RhQHBs66|%w7-v%+BcAwOif?*$u&&c?RpJYS z&#qF(u^{pGIP(ia$M2c3snrXPY>Ew!kh1AuN=A)-z+@Y>!Q%Ri&8wTMlldNZ56wJo z8X8Y>Iz_6RNg*qa)_AN%v~uFV2zBBhq|bFjSK1OOtKRbKNH)>8YS<^Ayc?V}-s#RB zl}sdJBLZX7DN69r!S1LIdQ4$Ukx8+)9(Ex7zMF4M%US#M9p0DVw%6ytzDq*$J0@!y z`8%u2>q=mS`}o-ER@<+lDtqe76**pj8w4uzF1Kz{PlWcJ`^34B{d8r? z@~+@RTmY6*lim43XeHpRKzDO;o=Z4ibCd8JLBf5H;M@4Oeq=mOQY8>1!P-0Ax=lHH z8x<{{f$q)l*7UQo@5h=~tFhQwGs2+0PYg0X^AFE+Cm3F|S(?kdu%wkZvS1WheB`Ow zS5x5vx39}8w$z_b=quG!9rNxzKOq5gzQh8u{k}BYUIf~bILm=>#OEWe{OcAf|nl4I%)CAe3ud1^ve|++t-2|u#GkYc10&$d+Kuc$Z`wyc3dw^&F{+X_Lj~jNF8@(3nL&gzID1 z;fw`K@VR*TGmM95#ffNIsPP2{~bLf4DE-#0LFmLqn%*bR;WLtRFNu`pge@NKI%D8W+kyFCG zU;PMdCiJHdpL6-#zkD`t5-t~Cs*uJzH>#|h7tW?qyI}rgBDe(+ZOU=`yLX3?YB_3k z2l?Qj$Ys*0!ncaKOwI;W+4VzOvX|+_Nh9$SRlDKqvK6hhG1t?Fl1?l`5mDLcRY#`* z?)iqmMCfx7&1BRQvWKJ9m;T|rC5xqi$oI(flwR*H%gN5H2kL~9s@0Tp^8q~MGf>H5 zHPrVcERU5zOP(2FJH=8n$0zIu*rJ>nRU<%gDnIO2yc4e^=3HiN&p&-R8O`I#$SQ1w zW&%aSfO}x=f2Iq3*!I@SnJW$j5B+0RzCcFMO>o1Y?&a8J;pevz)tonKqnz_}KknR> zTOa!fGWS`OmcAv&udBl)K4Z!fVV6j+xKB|)nGhjpo5CTqoQpDHs<#YR4IuSPn{qx) z;I!?EfT;&EqxJ#K>-F|3XAcl<+x=ML;06gjGx2D~Mq)F0mzCYFKd?@oJqSB@bYGL$je*fg+iNH$0Mp9W|bpP?DrS( zntAP6aB^t;e8s$07l2t2>ag~n_&)~iIREd5>!+P`G&69$5sdqY39MguI`!>oV#(p{ zp&;CzpI<^QsD)Hn+-%cckOKI9wIazd{)ua?EBvH_hNS)Nq08+4WksqMD8gR_Jkr%= zrMKA5`1j}0I^NlFgP7H?&FiM<^5wMj5!*#ey~$oHKH{f#kj53oU-Ioy8cLX#c^XnB z$fZzpfLRAWTqkX^grQO#IW#gnLN!HL6ufqAlAY~Q%owdLSA+l{(|K=!!>$M4%Mz}w zn|)U1b&@|WQ}31qZ)66pWqrOoOBg-FebLszy>*h!S{0d|t#Z zRXI%E+uVTe^+xImSh;;|KgZaqo+nt>rN79A)_bb=ULbqptX@RJoAglxg(4>m(MYxN z!1q}&$bJk(sN(k3R^=02P+t)$AI92gIiLTJfm2<3+~!O35E>*EYM4Z9iWkm9p6pIX=ZAXLo!HA>Z9|iER6}FenpEq)ffX)puevWU`MuWF5;s#*4 zLVg=H2EA!lu$BAg3_LZJSA4)}HI4 zBZJDxrhm{5CQucVc57Z${i;G_3XLXOuq_9<% zkH@kftXm(37rKaH)U+NUqpjtg=FNcO7$r8jrkm=$ID zZe#4wPmKqjTxhQ91WKp4-StsyvcT)zj!y)XUCq;N)<58yx7!o*E7SZWKuWzEb2Xw_ z>0-_nC#-6Oo z*E@_(1v*`q6u3z+zxP&uJ!ed7Af!deTm1>u2xK1I9K4k}`*-%IHL)b~drxbBgq$%U z5;+*Uh-lvDv5Wu?+pabU_DrgeWsGF_ILF-~aZg%Te(!4HGZBus6?zxI3r>9IGN5X) z>KPMLWAZG==@cQc7mm3j79G1=bug0r1TOP^p|>ihz3i@@QZ!{VNCxT7?q65vbnMpkG#){zRNH}cA-Ub6b3>ufFr3|)msAyx)rFmfeh@ia^%MU0bnJ4%wa*w3qmynFs*h zP2JFAaX}IZateCoO`A)*2i0kj(Qrq;uE@oyzp#PoeSO?{*A4!>NHozNl;uY^FOXNo zu(G`aY;{5=l3U)Znl^|vRu10jN+IdXJ?}Hcbiq|C|L`uu?JSAtD zwHFQ}igtDk_kYQ9a;hd+)Sg8)3~$Xr`q-!{q7OPe9wmfJ&m$Of-x@o zb%zo==sSa@=!L5+QYlaJSWPt&rHlLmJD_n9xj6x?ND5wp>CEk_IZS$PSPAK5-M3#) z4G#-%b@nO!l%H4gDfJD@S4k{fjkNDNkX=q~c<;P~9cVRjYU(qi%6GAu{b9&7MXrBV z84!CTk(kt<*vM$fkl15Jvy7eJXo2Q&(DNrLeac}xuxuv^`gqdRHzIxOH4tXPtK{Sb zqn$Zaoc0Aj`X2hYLMFelfk^H>*YBNO5{6+c9;nTp#zo2Ch$j`lPxJ;WZO`e|-}HL^ za76#yx=mgmgX^_(nch9`k(Yp@(&Fkj>o<|>x!DnN5^^Fytzs1>r;cp$=$h5G7vZ^z`LJow{wv zB`z@sQWwZP7FStP(CM43Vzk$t_4TA=uX4ziBl_!y-~{{8=Ebw6$CWz-4^N9;0^xS7 z8NdInr0~mz@ z50-CUiF|ie*27u7@m~1rw5}$tG~S$R40tShs>$?$MouE&n(e%)spAZ$4s|chmU7_o zB`B)AP*p}GOBCS_CKyqh-x$-eMg~Sz{2Qk0f^T;Vi_#a^F|AGszwRLYB^J`7_lJUH#v$mv=(0-w9Zs=?!)I zw(XhE4+V~*t#Da8$l073H;$)&tGi<{?`TSy#o0p&{GA&bwdZBnRo|>GR+m#@v!Llt z`nc{?A{G_SVIQl}hp7Z8hfQw4osRDnKLZ(8(F1~mUhP*Mk>O%%s%@Tl!$`*tBe-M= zlK^d!MY>G2Gb>%GTqUFBXMaA>^Efli>~rz(-iw5wKWvdo%lmTsX0%1jf9A5iOfYJH zNuFc(QopGbwO-1WTPUYK1YEh7RIA_DL#g>2 z{Oe`v=C1^<;5(g*uHg*^!dLV&EGGds>Vi1D_JJ{^e%ea9sEg1c%h=WOZh#{`LD6<@`&MnkKTs~!S!=sLr;_rH;)r(UiVitdkWBG#u%W)R zYMQ>Sl;*%Jp)X%r6l^x>SPc@AIvbZbAv_s>O&66hLQ>O!l^b^i^0{S=fA)@@!_Zm% zTQ~7iPaAmOD1Uh@yS^1~dpH!kL3S%CzB)D=ZBB9OZP{JS5)_&M-JU~2f7ks%T=f-pn|Xdv8@AUf z;vYH5%68<0okj~akXzdu=XHe%hF9vlVCTiNXilD(?#{1~%t}Z7KNya9#HcRyy5Fi) z8t+MK%|*f579a_#XjUb=q=oRVpe`ux6@+v}k;f}JK<$<#*$6zcRV{u3kE%$*t2D8q zF;ENjPmQi?x)oWu0r$;6Vf|G#S;2&$Je6?NnJ|9y6l*+kYYb3Ne740pb?|0tl~Y=; z({NY&W=>#xClm9F4Pksp9$2_uv+=JvMfdAT->K@UFn-iqeGT}4ZpKLXcQkpie#qlQ zhuyE#SG#OPrUYV;G15uDN7#viRH7p_?x+jt_q1K(k%UIux%vv`20ewVle!SlYfU*8 zhDk-~SMV!NZM%uTs)hM@F-mLX2ig!^4vKkJ`=5E7LnG_5U>9<0+>PM8-+X2}ABQ(b zp5{^w>RJxuoCXr>fG_XOIi`eE7r_`)E(hVLda;BznJ-|E3OX+roK-Aq)hX4}tygbg zyp^pqIV?_5{WCR6XWcG~+66ZVb)Zi*j*tqq*8CBNO?aC1r*ZlQRmjZ1`eyy=}gP6@k6MGf}h^Rk>!c}O3R-`Pclyg>&zWETsYfTZu!vn^?#cD z-Egfy?zX~FOaBpH$$M$+zv-y~>YMBXwP_}1YphKOE``|evvh7X%<2u&qJRwoZ726q zwNrbUxHZ`8g{p`lBVAt<=nd&?_JG%Ftv*J-oKRClo1Sq6q(LyXi&g3+kBu6|9mS82TM3B# z!1Q$Ky&~izZw05iD<941#XAV`pl5L_vDE#Zb6V>$Tz!*p=1O)!;eokMn_HQCh7ej| z4m>i%EU_ZcNhNRjyNrSo|0>LByE@F36Mao6Bw~>%LAgdzf`YI}gL7H~U46$H z6!7yMEjx=Q_Nq_+vq{Ce$@kzEB@QSks&!bd9>^AOi%B``sO1Fc=FawfsKR8g#vfzD z9j@1*+(Fl3tpEsp4JnJMC;`bXNRdv@{AOF+I)!*}iB<9cmQ`BF(lT=Jp-r&PxURC@ z3T>$nta>%AA=GFoOFJ2JmR;S&3e(e)e15OYky$kLkuYPx`SNGXJUZ3xS;#>X+A=2N z{Xz3|l?hK9&}*c9U7^b2`Zz3j!(uM2yS6pT-f`LEavt>?Qy0&+UQL%H@+=N#=EN%24{_BK` z0CnwyS7jEw>uH?TLC&(_Ax!1bBXF)nr^XCiGQ8OIoJdi_n|;<>`k|L8s}-JY zeQJF;I0!TINmu$27Q#7jXQcQiOb2^C){GMMBnOJ7Dq=UU%0It@4G%iLq%p*1JYT;AaEi)O6bjd`DSlYhXK}Rc1 znj6PBxIVnr-*H`k>(S*o$(lQq9y;U78E749eg{4c~e;qmuG8P zceZ;Li)HZ}R@#w8}0uN#_)4Wz=wuY>Q`*tY=*-9ks;4h?d%sjOXH3s z(uL&(Cq@xdC(O?L~RQ4ncm(9(d^`_M6Bt5o9}QaT3+7z~ylx-kIxTq<{z zc>-LH=EK*`pf9-;IoBrQigY*0b{wM zN-e*<+*4QWjJ?*N^*}SZFdg#4VHxEt?B<#KZj%a#8{l!&N-D1;@o&wxK@{b%%o3pd z-8Mmut<0x~k^zgI%!LvN6m3eoQRI@%P0e)ajpMD35m9YU~_TC$PE?;4#fRi zFssUaiL-(|H%oMS5FxUEO;A73GG?5~Xt$)VEb>`0x-~?)D&ixvo+8@ChI)_xDgIiO zNbf%?ND{&J_pUht3|{=Z^Va}qJGDi|yDJ?PtBF`0rC)@;3b~1Q=3tl|=d3jmC_J&B zcPuZ)vE0~pqUMrOcIXM;?yniLP9mH*L*-bGHxP63kJrRgv$FX{SK3yW7E5x0Rj6 zfdF3f>)W8J(iAn+L8#R<3#F>!cpJgq&1yq>Fhqg5`Y7H_(+^hm6Trnv@LMAXjgMc{1qxacTt3)M+q8IOc_#5pbDd{)g@_9a$#C)5sq{UL63(7fv2}U8^lDWo9pYM6w z>9}W|z;?&hK;(bzQjxA$4wGuL5Ft=KPM%JK+nMXXRKk_v-6bv{rq4CIap%$g{Xe&3 z%I6d0Uz1tEq*T%7sdCcSMABsj7N)nD)caaHIjnvktF|_8n^;NCQ_3^r1T2Pcf>y-zj3k|fNJwx@FQDZ8F z-ea14Wk0a&TvG$re=aqq42{DLUP|<`G8U``k##FFcG#4JN^&@R%Zt^W$o=7Q*_2FG z-6W_L&4#m;D|JetoV2kTFxn6-QyD?*xtjU6$sA)A(bF-%8&i&@VS}}6cOE?(6laCz zs3s}aDF1c*7C1gcU6p&hK9)>>%0HND(dBvXF7|GWT)t9Stk4jq{W06hin^R+vVTTR z(fQcQ=c<4|B1<&y!I#!#rS~NfWpjIyzx*5)q8=+047d{2(ly4*U%sC2C(+EkA}wb& z_-h=dueabggM!Ky?9gvUn$k{z&Wa7ciDeiapSrAd#= z*Bk5*8g&=k=qp(W1FTQROu`8WwzSqQqkakuSQPo8Uj<9m9`q!fMlV$Sz~Ozy>vW{h-$d{56H;V-F>W5JJL8Dwcz<1iP}&>INBw%w zszG3Gv-Wta7!&+hDtLH4LD@;ni@lwiOo`U6217!Q?ob&5>?`UBt8GT|xWX?^N&p^-cWE@4QOc_}(IGLz@$5xW=+2 zRs4pz2nnSa-QJNOCYQbW`}gwZfPk;;<{SjbHL{n_pCJ0Qp_79W#ivPiAo#uSq~)Xf zMohE@-0OOB3tajh5J_GmwZ6iUgqPFiC|e1iu26C9HUW$n1+h8s9h9uzE^$)JwlBk_ zHke@Hq;>UUHHm*ypW>RWwV1%#4T>eqgA5Js} zmA|%dBHMC>flwiKB1Gy&JFhtc4S0oA%oLa7vv7SFmaMlj@SIRrK&(-0z`Iy%?GA?@ zylCIdQK1Cho)}a@$c39 z@c1_kBNH@|y*p(c7>iZ`H5`^=0+*sUHJ9%c}$8tC40rsqzDv!9H_ zHj5C;T(&oEJkJ`JAOeJNE1n=pN=KH@m~z%zT+H#@ABA?E!Xdjb^VOK%bd6DJpapbk z%M&hFSTQQN+PvrreRjR^OvpPwtJp~^2NV-QdFmOqLU zfYtib!gVR$jl_|T$(X8BUruF})&$|S(Bu2 z3*!^;;#Tfa-d&|u^p8g}1eo*)B6$b*SLhG4zmHCfT3wzXz77=QzpW*Db;I%He0 zyRAI8QJ8X40_ysQitQSL74@h&9c0>Rbww`2IjY&J^HJ~Ezp4v*I2#3M-$)kpgs=_h z8SGUxDbws+klgxpi6Xy;m=?6}bvkU03KK{!XDP$2s@AvYEgv*5?_^-FM4`=v>3P;_ zgq+W|DytIZc-!T2n4>*b*;T0SRScJ@>_Nb;= ze&*ZitDBY$2zVRt7dc|8%4Hs?C2@RPV--__FTYD^tKe#MzMa8Gc9xfrNUgAmnmsBo zTd_C%(KJ#{(#0Jte>81P>~yR^0qcL(-TRgq_LiqC*x}HLXbC5eb(8V=tq6gRm!V;T#VCbp6d*X%~EB-LjRt*#oRVt6$Eh&@k1U zN}nP*mA@-S(1h04Gbxe0QlYMsPoAU7UpGJAHjQBU)_>I1qZsWXo)2z{=)VYfXI4&q zUTWrFVaOpxXBOCs4i73*6N)?{#$N!YnLBA?;eNg^7p5x-O(u`Ye zcm*Clw$<$sNa}kLyh43zG6Af_rM$Oyye1aSss`^Wn?#22(I9PLDa1R+6Wxl9B*?&& zMR8PDGhB7-Cx^@(X4k7LhIx0=mGPGXdyQwc!Bqs)<87gc|1q>%d?$xoTs)hLtJP|; zg+98%=-1cuTKM|>Mpm0+r@|7hr{(@-%iy2?V^9Rc97oAB+FeR|`StJY+8>!+7LSn0 z@BI{Nq0?W3mz>S4?(A9ix1*eet*a&;byTxNSu`Fj@B6;Fc6_gheEmeEuGT8?Z=#nZ zpAdC&9ywZD?_;xUrY6(aP5P?2O()?%Mmg!sbUg7;lCz52A%t=_Is6BQqF{C7V<-D8*x zTnXdrun|Iv(vat{)GoYJrn`{Vj0V&y!%^Mz!HubI z>RBt)V|zwCG&&5WnhfCKC$l}D?N{l)d`l#tsve0W&j+&f=b?JS5f9RX1!k({G zwCfQ2I#>ryg~!cmr^08I%gYZ&XdF&`W-mNuxWdHBd1cz1W(#EV&` z>N1-~{bz1Ss`3Ota|+;IS+Mt(pCi(J6+<5IhMl=JUKdzM^Vxo>@q~~TEjs8Qpirg% zdg5?BQ)4m}{n0i4e+>73zg3AclGT2(_tRoz8w$ahm@nVoNZhapcg zbvGjg?@%M=pz6zhZP1YM(q06p*-%vyDyRAxN`MB8`2`wW8?KN(QYbxXj%|#n0q(wC zzEF4m!m!xOH~GEqW6GnsY|aN;uiIp^4351voh$e1kGrcl4SI@N796VYf>$kk$9=4~ zj!3Vu9cL)D7tjk^fRI+RK`)OvLb@z{kc1-GHI0lh39h(~t`I8AHpFJG zR{+AV!i1)ziNkT-@=jZ4aJ^(Q1_EU)(wj8RQh@G&X%=tf{n| zaSQ+P*XeO#3~z{9n%q9oI!zsCr|+ukSB5@cwXewJW3WozPhfoBmF zYHpk2&~J^Wy|1oN4`|xcCj|zi11WtvFNEGjUH12#yakhOT9EoGH^&w7PPA)?HjV_N zU=coXw#ikJE0I&b{U;ygY``;p9`i&Nw|3A=35D%8YO9O@6)T<>!!2gRi$>pH-Q#a= z*QgBagj;=2FU_GVTNh|>m$=aIQ^j1`Hz|43RkEi`{#A|N@Ek*#gAuPgE8dJY_Nl#N z^PMj`%3>aL+F#3>VapkAR_~S!be5dP^3Du-?1937q$5@7D2?8+HxyXU1WE-E9O3B60=xLGcP5(Yt)D)a z3`<{4slI={D-X`2%ntC;y4!!8w!b&0dR+DkhOiqKxGGg$dZL#tNOHM}FG~4&(bZiK zOS&&;k8Sd`@oKik>N5oe)ujA>8)*v^2H!f*x-_C!3K?&ID@kgPET49P_njO6YsIrj|i*qMNcghc*`Ad2_}$ zMw4=OKO$HuoFrTKH}ZO2s6W4SrYD93PKy?BNIoXoBhndGubz3;*XxUrc`Z$9H|hm`gO}7Y8oe zm}dolFaHO4wv(KlC>0Q^ZJG}*U-jEzF}-xXcSy4{HTV5gpk0|R7{TPMlV@qsT*6D3w$(BQgrT$A>s*B1C#}co zaw0Cvt}&Xq_}VmJn+FDJ4G(Cs~v6Ywmc!eY1lH-LcOM_~NeYILA^a{l>) z%*r>%_0@cZ)tsQ|3BuGrym6<|Fyr%x+zc$xnYd^G^LL^0dC?X(;(!`s^SzY_ z0%MPuQ0_-w4isy-(Pw$i3lYvPRi9)z3A^<}Tr@`?4$6OYV)0o+aw~!T4|8mn@15I( zm;9A19Q5PsS3ZvLfg_7GGqN-Jm{6D?3Zjm<9;W_bsrNnlL_TZ zZMGZ{Ld20FqgtcJPo+u8Gx1x4HE8pX;^)WM@AA>Go~`$xO~M|1hO>hrQv72+fuMFw zXybC3O`rLHjVWCQijhY!x$@3x`$q3ng@no11)Hihtazl!2}*3_ncy2bK0okf#ar!V z{CyTVt|b>c;Eb-Jxv93MyjmGX?+f5+3w>!1LcvdK?$8QFWUv*Il-9D9NXvB+tP-W9 z3V>Q5#s!G#LG)LYbR0itoi9U|=qbVaClGFmPKN~4)P7noQrrIZ-j$vHOSIcCl7B^} zfuG^Q!$E0b1KttBcP7}n=_ zlOq~}SSx*1a!r%9BhP-F?L;5ob5EVgQ-bo+i^Gj3xcXB>Lz6Uqdzdum<4`v!yQcI} zh}P*7aTSc1apYaq_WHEqCP2J&&N5;lzrwIvlVa{@Q*Bh1t^^X2$KZqClf<_12h_^%2$bUi(tPz#T6t4NKd zN;e;rV*JQkkolhnvAh?C2&V4q;QVPN@0jC3?*#6lHZ2>)*u_g&$ch0o%dv+vZ<+9( z>qd7&42~L1tG&pCwq~zV-TX+xFO`M|`H-P#L8Q{O1yJRS5}62BCK;{2$}no#seB^t zZS`WiY7v^CfLwj;Sf4|)=`zZBn&FZS4R0J_eJ4jpDJEeDOe+$rY~j*@vWcU9pc$pQ z8O7LIjg)W>1Vf)Xl#j-*5^4(*XL75cbnExV8IR3Gyw>#nAA{Y|52AuHyf<@|j-Dw< zpq5u-#LW1(3*M}_YD9P>CE~6-eaxm=ZV=La&$ac@k)s_s&2>RoP*fn$}aJ06YlktLP)N+9jQ1~s>!IB74ws3*O-eIkCRSv{FuYqSS??{ zjnfMCZt2DQH50j=^M5rI*gV@-bI zR&(*|9KO4rPy~xn(P)_S&64g7tJQOYZ%khBMANjQ)Ye)vqr`L{dZ2PPCE$y+^&>hS zH^bjk3@Xk^W>EK#0^7V2Fs=5CKB*&|8uhe|H{B_xyMwgh%P*+G<_2=BHiMl>>vDj+ z%cxa%{j+|A;q9sJHg&nqztnTO1$syf%5EpSZt#u4dYRvfgP z7O*;T>s+V(`dI9|gbnS^`cEA_K`d0%{<#id2>*k6B zQOqcF0zFT0s?|iq;_<5@RQ+MR;skuJqbTANDL6Z39RIfT|MV5gLWAp6O4ZNhhVa}ON6$v_O_OzP(6UVLiFHZmTtF+%5UwR0(kysTn#9WVwtqh3L99SM|eo4qam43ly zd%oAnEQ?K3S(am`H{kU0(Te}7DvM}|pfv`}$F2^gZPG;dN;rd94E)#~nDsZe#`w#7 z^;L)nU9*FU=&A+-b@CYIR!G7O85GJ1I6Juar~gEt*G59!&g9MgaoD|H172*oYTF~^ z{1r_ahog-s|CIbuM8%Zi2J8m1iTV$E@Wr0QOXR!o$Dy7+Di)nE5SeqNvM9J-%?nTfFM>Zu=E9;t1tLG7k@K|dbqIvIRh>V& zm@Lq%s@cO9fPyo@JKy{Ys*%?3%NW}y3tfJKh*U8~R?S5`__4Avw?10Z>1(nDdesR_ zW4~hU(BEOUeY+0N9acAd!)o_RXVyNL#iuIkAvkX@aWBdB@;$%*F+d!@w7EJ~7=h$% zWX5?ZQ9%`U%2%=|3aD`*Vw~-z@+1*jGruL=ta3Wacsb-t_E5`mQ+ai8&J=>!@rq9NV>crLCULb@VjGq^0ZfVcrax9R~0@mwD<(BrI5WJ z@Hc0oExor0_+g#N-#^uqPLOZ z*s6+u@g<=f&SYGsr~VXDe&wAC0WcA$p3cEWIkW>-wS`Nb^o|tI z6Q32hxUdIE#bss$*C;Xfrl(3GYfU}#JQ%7rY4d?0py5G z_M6d1RcW$1&fuQkP>ECj`HzSa3`V=w6oR~XwjiQ`ee}6hwcd|SyL*YT3WBqd=obpw zs#dP@nMwEdSnDkFs9y=~9)L1{NM{4K!Yu zx2VOxE0g>35JIKynXm;+9B*HH3b*uIwjit%A%LJrTfE}%pr=ZmM_=mU3Cf-Un8H*!axr6$YYA$($L4-tGh!fY{qgB>y>GKJ`tvp0n``~x13NU~8P$45DuEoGRY_Mz2<@3hqirR8{aoom6CUn$|vBJn6 zaF+xu$^0WH_88|4Oy{8Yg%`RZat-@upTA<~dvbLt+4C$CnP#(`TCAM@x{ruO15I1_ zsG9!qQ{Yz+Z=1SKK{5PRN?#0mc_=1(sp!1oJxO}5$g>K!SQ-lWCb*Cd7is$+L%S#C z{ENJFY$y`hsGXUqiB57(gd)(V6v}!N6bczpD zG+=ig%?{|4kwPB4dRcT|G^Z+X_xG&O@qdtB!6X>D4BrEZlzKt8d4Tpk|5cQg)yJSp zVhy3pW_gva-L6lA?p-_aRzFOh`qZ;H1Qdue7|{)&8Wr;@zExj(9j|EqhFZpzun-!X zXL+9!JdUCbGD4LW;~0^qYL~3poCt}@tUg;6t(sojU*)UQV#_5zajLF&e0M(Z68i)m z4*(Xf7sm>dzmj@q7&E{D2H@M5qm)}_6Ja*kY(X`Rjy6%G!MdiT=80XN9yLGwV?6z4 zA2uQR-wuov4w71HzTmn-@uVkigKwKHHBP*%uS z{HMj^+pYOQkGeK&=H$!S#6QZ)KB2YO4(QMHmtKlJU-#R}gwF4H5PXGmLYihRTH(v0 z1wS&zI<-r4`^nD-Tr351ioO;3#W5?tHMsJG5vAuhCNSjL+L^9kLcU*ZzA9(_4*M-Z zf;LyCeiI<&VJhIG@L18Y%73(Uz%DUW{VJ4VzH5lviZo~2^z(k&-C%nd)dhu{?;5+Y z!y*mX#UfA!I}M#O5~s|H5$=G6z&5zS#~17lL>qhlB;?mWtd@NBMA;mMu4K3J458+w z$j$(9LYB4N<=MmHSBInlrDoiDJCd;kyxe-m-cIEE-e$WIZg7v85OW^;_Tuc5;FGzA z6`PU#J%9t5@X3V=SR>Rn9nNWDmkzJyaG;j{{5RFabv!oul%9k1Z1tQhFLRyGsrxw5 zGV5Z{VjGS*uV3k2PkTW7$TlpBgqRBaD~Y}8N2@HuQ$9PziBh{H?E#mSuMHwcoU0^` z_+j>7cnAeFAO{$hgo}8uOO~j-%?Ipo=*>8CQ2yax^G4GnAMYj~(dr^D1G>>Ghav&! z-r0|y$>`k6Buo{~BdlDjjRJk1EjAcGwz)a=O{cWw;yPoQQKar(NnLy-e?(oBPnU#sbf8~VSVvAy{^(*z3i>_ z&MPas5Gp-{Nb9;v^-mC#shLBr|Ph5 zOvx24We1VH2Xg?K7p%)EG%7nZ(jb&q*ELkLIclW-z_r?cv*-EzQ{C{v`xADLKrW%) zT!Ap00BfqZ^bfFYh2>yF(FdoSbbJ4Ps~56o42^I_l-oJ>_^DZjVJc*lKcOhzO9am*ou_W9iJ{PVf)s%MQ<=_W<(gPoT5O*ZhPt5{}BPAq_hTU@?by z&k^JI?#gv9qWHXe(7kOk&*J;g)}poB2G1FbKjs8?aH+PND`$aJCEby^nIF@wQ?*10NzSQrY_tbc<@t6Ik;(QB^k#JWkh_i9Ly zGLzm-9t_MY#;%$9ulka}%q4!E1CP&K-{l*1<~Ee+w<#D^sCJNuX!hp-Q>Xa`HzXcMxHs<-j<4`_9iczHqUOwTnYFWO!NLo3=R__cyNFS+){$2-en!dOAKZbhJ?v=uy z%^^OC4h1Zu>gp{c=t(3;U`{^1+s|UE?}~=r1IQifoXGh3{As#k^g`;K#D9!8$JDKG zxs7h#tTCe&J)Jn<&5MEUH$4-!9G~*k}YVRBa$0ESgu|AH(|mE?~1_m^?6m*;GY!!wN;ml zl?TsL=M%M7fuuRd9j6;MgAjmg0n0{#zRT%>Vj7k2BBy2hgjl-|xM$iGOT2wShtdIvVWMmW`9h|U0&DW;% zwLp!6OO9pJHN`kn1*kwI{$K#0d!Ke>4|kZiR-teUeIjK(W2FX#7YpGYTU^ zinVljJf|*FOjp;%G1|qi99rotX~4J#zet~GVDwk7lxm)R4h!4K(3{&8SpS}xiTE>4 zop^*$TnZsVb#vhTT22JA(_)OCogl@H*et9Qyw+UHJkpnVdu8xHu76Z;-Uh#}@<77o zh|VsVN>I8z8`*SltelaK^Q6gUbs8fm&x=#ey2Nt8-SvY}2IWga>`}pBD~M9an}B*x zqHGrt#)3}GMC0se~~6%T$o3BT#422!Q7Du=XRn4d*CJq8Xp7#+RJ z#8a_o`+qB+_kbDL8;vr5=ia&rhLcmK;rLFe9;tyukKbqt zZ!q}!IXViN3ot?Fwtz^!{IS4PjjE0Qg@weegSs~8+lP_^ElXe_!JRQ%Zhcx->Q@`G|{5#GK-8u-oEy`XBM* z4eD1uCME(B_#e9Izsftw*pt}wy8CL$X2-fzDK8ADL1l^K0dGb|;~Z zt~%(4z3Z79M_EzHc_9NNGmx?v?JM?0a;Z&Eb}{*NZ&N z8idh+VW>2KZwdu$`O%td`lmHy6ggW-cPC3@hg|S6N7!U)+ z7xhwvjljQ#KH9KarYF7iyi+aJ^R$5yU{vmAU)GyGhg)2C2osp1$|cAuVOdXRQ0=yo zMAw6GxN%(WUP1|Bu}_PmJ?9;qbou)&s#L}G7xB_`xs9(@T@nfQwYz8y@Ky%UzP^8# z^--R8v$+ZFOMuuQ2)NUyOXjGS+I`xEoz1tR5=ppZ7xN*(rzUx|hINfbV+ z^$W_5`sAPg3T`;QTrnu8U4GcrL=d%EsB(%T1C{B#J=ldR^9;hOF4K4tDyRT3`B0=>o_MzDp z?CKPs-%2n8t}jE;y*%03e)>U`w0tQ$oYZVzyt3MqykJe{seW|UMxsW$F3aaqLj|oK z1fCdM#p7GOxZa5soCilMmvAcuS+rzHnaCzdckp=zQ7_Hj7~ZvuMnQ(XC6CV|CZM1f zlp%ZgLb3=y&0uWK(P>YNJHA^v<+(2S)c5e^(F+pw9T>wNteBlcI4Xaz-!NDV^O#%B z*&DiKDH!g&=UQ=x9PW1b8ZWV-)>>vSH0Ki~CtC)9fnnxcRSDq_9z}e*{|{hT-hByi zRRmP__vYI!EF_9KKGD$6bQ#}OmE|OE<@Zv7u$peV2r$3@#xV}E0(JZ3Q5`Jy{FD0A z{@($1tBbi|hn9A$w4N&4x{)0GuQR6I;l$7O&XyyjaTBZHm&9=lYFBhmaha7fHcN*gR=ByKve%|Q>k~^F^yL$KRYHVbj z=6AkD2i@p1UMy5JJThL4T9t;$T+vYu8O87ME1WoU`Z4nmW9>l6_hRSL*qrt};oV&O zx|WCHJ}8t*GRrGw4o1z_M%G-MVwrj+zX7G9x@{swq-V86@Lj$SPJ5`^e>N99)ufQsICN*wOKr5;2V3Ur zl}-4%1s7ZZ^zgZs*nkIGVfH8@!je6^ zEXV6BQwz(0sFL;`;B7m!i4sbVEHUvR- zyKOuubf5pA*?P?9sYU(k;Dbl`r0{nG@TeDEZxGR~EjAhfK4#oMwZMQYy;s9$S~| zvk@Nbc=HIf!sr%QKzK~^oM7^m0L~UYQC@;lnmzl+0`1&W2QmkjmV2nMRkn|c5-{G zOi~C@*+d$}0LmGbBK5;#{FDw`;kKH9+wm!-oDdyq_Gd^-^ef}I3c~QBzKwXK6^^SB z&zz=jawX>sGeu>)zn!h;Fjp&~6e&X8(;s?&yCNG*zkS55KJ;iuasC&QlnW5!P3Lg; z(c&KTI_*%#>hZurrbn$G6-b~8L?%tFxL0#t1g1YX5xQA8tZ}X9z4hnMxhox*3R;ax z{fRel3LrqD^@~+4?oIO_i1^Q>r)(dk@@2}Jqbv}2X zn__iRQ!W>q9#jUI7_Vf)xE)YSr!c1nH*(3-Oc@jBQRB&73Ds=^71En!MO$+&<_kg` z`r`Ka=brJ+J)e>G4vH7bb!6hATOKqH@c8-nnxHA`7CjdnV^)OKdc{?4!%cV{uIzC_ z>)t$XVMsZyyW^`YuroSL3nYZO2Fqq@!aiCoB&OY)2`+o^Mh*_$1TR2 zCrE#r(Kl@b(t8qhP5~d`LmxD{te<_)je| zjCtSg%=pRA?#oziFRKoDa4K)#QHN6D1m`}k6H~LJDSGZ|%Vd84H-6V~lTYfY$5FDy zdv_e^6*DmBdTOcZ(Q}~y**-?kxPErt*Eb2*d+P-;SL;2~9P@&qes|UCYCk;Nm%8Oj zOR(&JG!oz@EOUa^eT~cVERNq6S@T>b7f&zl+%tT2`dFAOz4qeO;tMio`|akGO)jYh z$;4rX>jnhYP3GH*)g5~b3ikBiQ@hE z7Q+lCn9A>KO(z8Xkc%o_0x12=0WTfOL7o!X02YstsIKbLwE**(i~0DtaI^Pd*h9Ej zNXl5#jx2GmZ@nKgb*64a*wSz9FCwT{li~t-XBjy)bb%vg=b!Yjt5~e~nMi8RUXyd? zrKIay-A#5RK|_lTA8Tbne}YDfl<1Uw+OI#>bD#$>A`Dp0n|E<>D~9;G^liEZVXibN znvX8RIzM_=`>RC?t)s;|Q!^Ny05b1Hx;l0by*qa0-=`bD{J2|4wR0|tl^6hNweT_p zQd~6ni8F7oqDG?P$}{Ka|H9p^f|fRhZ##MSW)zRvUB2VH8}@knDY;Gb=3s#TS}mT6 z>n2uuS3@F&YXv$_)5;O5b9d`-lp2%eT?4lje&egY62)+kAW82^_VlKFp}d7Pm4)oN z7b3vE)IrSJ#G>zrxU7Mm*iUDEPzbD%`I#^gv+Z(NG0$N%qA3 zrnY_{tW!+4qn=Gi_F0_LBqc0ry*2C&ppHeMra1Tr+bePEZv>d=eEm4^MwEq|yR^Qq zwkhqZJIpj<#i{8=!-vMYS5el0(#>Xfe-mDtOY(%(^_+ud-C;nQ2h1F9Qj|xJ(MeO9 zQ+sNYbCvxvpIXew2HH(*0nTReau~^nzx&>6?xG`eQ>Jj_d47;LYzJQG$$EE8D$pD7 z%(vH-Lk}D?xfPRfi_U-y>hL+Bbt^(av_!3LEjL zDq*FskWP0>eTtzE2twJ{G9Ki&F^|5xZ+ALqe19C#6}(U=q441GyCrzF9T)s%RFt0B z4iok^f%7U%Ye*|!AF-gKrw6CB5A*znGGK*v{7LD^`HcG_yC_Ij9 zLd~=rDBLaH4Qt=qA2m+-FX^PMiRh@rsQ-HB7r-i>xmjh>XYHmGs_77HC};qwx_db1 z;8{!~q!L}WQ1sGaUFoB+=pqrRuVMSAR%4$>ITZtGtv?;N3&6wO>LTH0-FMHdzF0$b zlJo1jEd%^RHR0aey%WnRpNByy_^R@TlxrXs@(A(O2s&Cz*`Jt=QDh`O++&p~-cDL! zi3$yT5w`l<-m(L&Y~i%)`2}hgqyf;sf>N8hq;6#-%mfTZ%rSF8_3uE8^fO|1Rk#!e z(P8~O-~J*=Nz{GC2FT?rbM>w^S9?v~xyix7qX7m|CsA_2OjI5nP|BnqxQ}$ea!muhvT3f^8FATvocK@@}B$sW|D^;K}s`5r)G;6k1+>k*Hc+5FM=LYIlfB~v?d+vC+E2lDkqj#gcv4YA0)+KuGF z7Ml@51~*8OrQ=z`&V22)OB_}`DeD?7(~L@0D2$R%jso* zwFJeo=Z8KuP?bCQRTZJVu0mXT*g1uTBh0KcnbW5+ylL*J?R*LD=TyH8#7)$(`<6#$ zd24A3yWWiSniH%JQXq^#3miPhPvTo5<2@F~TDE|t=ebbo3t++F)Xq8@5TP~KrDX`? zeB-#*N})U6W3}(hyVsvH85sl)7#3iZXPEPWsWnrrix+Kq=+cpi5B9ng6w3!vPWTgR zXh7;(OUy^=3@j(yVo=Kp_TIfKs8?bx&CgLS@cX-n7p;#^{@{bZ+~&LJaI^Xx(+N>g z!iL>3EzZ6AsG+alP<_!+ONV{C5aS%tG&e5q)a|wAbVDyATe6rUl%6wPqxM0Xbxth) zBsN*-;+B!k%GyVKl^PwSnKF^C+RXl(XZk1D9&th!3~fgpa@L8AZ4dHnmk%vPy8~|n zr79;`d32f7OLW#c(4b0Vj`{KXU~>7kmX2?kZBc}%5^7c4SRD`8Fr zhz{KAi==6ak2yFq4F$1LQnS4;t|Icl135C@#==X}GQla|9yCanah-)}0?}}h-d-;T zv03rPGwk`=;vb&LW_aCvh5I#CW5y!d_i`QTT65I_^%8ZXT)WI>?!H)HGSRnnmT9Ig z7IWy=*F9g}fb;BI z@(5@`6Lv|0%xS7wq(+dbY*zS+#_6M(_iVT1=GG8Z{LfLe*^j?3xH~98>c0M&`({I0 z6@oGa$4|0*Pb#vf<}wx%G?)tmBawZ#^3?~M&c7Mzt^14Y4ry!Qz9tV0L^ln-KkBYK zbghoSk#fnvt;)ffoTGLBPr*tFl=O9WRZLfLV*J&%4UpkxF073`$FIK4M>0#~FWYq+8@L3N&Fv>USqh67D(HttLDG}jSs5W0h3+_e%~uP*q| zszCbHMSO~u};3q06jYfW~ z%)iX!C_6bNp0Lr*7aZC!mO(r*J5F@@$2k>AJbAvOYBlwXVtl zlNTObTuu-CM%-r_C06VEcUu0+fnP`Ae-L(+QJl^=9ZBx){mV3Q%3a-@2MQZ17^@mawmsjQ=t zfwCM;#A}#aO=U^At6?PnjO2yx5cb)-M}VTwHSUJ<^{O)J>i&3D^q15aw>OYJll?<1Wr%mom)&=`UHbZ$OYH$3 z@S#Z+3k^@dw&afJ`Gcm6#|H8CTq17&hFrdae=8neu{Ys7TxHNM3Z|{^cR}Ru*GMnv z++b!8%kqz_9~mmqh2F%X-D1&L0CK*Un7%N!4jUI80SS~&nRF0E$t=>H1@xkwqrPk& zy4qXT`Zw!?_DDSDE2u45nulqv=lW06xxd0d$%G+vPG4Hw?B!w{8Yj`aaYi)qc-K^P z5>s_!@*=@O@OcAJ*z#QBgEXaN#Pj@Xw4GfbrxG(B(jJ4Q41Y9ZYk?KzvdX&)QDQw1 z>rFyFVU4mU*DP?tYJg$n7y=KHKYKLTCNNbWzi`QXex~1fK~O4V_9P1i>^D1ahK+L$ ziyYjQ4mxT_+$*a;KS4rdun{xKv3)G@dk66|e}A^K*1;hOdQ;L(CqyY%Wc#itW=9)C zURKF-(aB2sDML6%t2OL&ovKvh?VwT|9ijG4;FHF&4%D;Kw3{+T^9~f$qP=v2i`l%Z z+$UEHJR`3zQNG~FnI1Rr+aRs}$t_(Xw$DT0W6>-4GJ(d{VC9%5%jNl}aqTEvb}t?8 zmckkBM`xO@F-E{i}|={p%>;5{p`go~Q6 zjvqm8ESCf#H-x5G*Y6V3s_<|*P;`#$T(7a2QeACq!Gb4{w^oqu#bQI(LP99K`X)`ffN4l2l~qd zZ3ik*#;&ib%t`W%gJfQI%q~|4S_73#iWrfCn4nwfIQUouk7G$ zUnaFOr&|nFLw4xyoymUf8w$g&jISa1+^JatSOBu=44@Xp8A zh~`%C>oC4vN1oN`e$AkueQ!KTr_ze~W|1q17YW5}I8!(}W^IIMQdAH920i7=@Rm!4>yNA0i zCU>jjzWPKBy#8d%F#0y$uk*RQbi|Kc=1Z5ErB9|Na63#%4enyyg&LPFPYV9*u0@Pt zVgVm;7`aR)#am@EOZMAtHEqKK3E- z)&muEP+6BbsdMmG4Nv)2^`h*lL1)>pj*03itzx2jEk7qiCwGkOe4tb>a_~0zFE4JO z6~7eCuW3VIfjEm)=GUL*I{=9tZ*BLSS6#wQ;~yt|e3Bc@J?a&&*-6}!B-VW>LeBqj zlkWM{T-TdOdUGN{pZLkv`GVA0DdzjD>Z3a;HHfO3y7mPX)C(~MP9%UtD|ZY7#Jbov zTyht5pKabFbH6~0eefKZ(}ViJP}ltb5eQpV>iKH>DwVKaYdn2pn9FodqE_ODp4^!q zig@PXX6dGquAwI1%mWkitmHD0dhaVS^%_05T1_x#d}+Hl$Z`d6U4eJovL!<#Tcu<+ zp-W0^)(9v6b9Ioo>QvEvSiNSje{F*B=-bva@{v!DhBB-6%y4v0&By+TIw{nHd|I49 zQ{x?F;<4Ah`1gXihv&Xe1>cw7p=7<*d^SDM96#VzG36Ox2V23Bo_OYVJ|`=i=*Rc~ z*|?V!!UMmJ;&AyfRHfdOLrO_%k#Bl_*nyQF*=~O_dB1ZdUwB_PjBvA8Z+1frVu=;gT6l0 zDVh#fL!Kb5y>eGiQ(lf76=!-H5}r1Ww?u)yGRmDh?GzJwBc0SFk=cMehL-99DR zLJe;1n#&L!cI$&`fz><&nlZw!_R$<+E$ZRx@t&rgc?4no<6a;wu%m9idq9m+F&Uw< zs-jZKTZ#%o$3^ULWA%qtH6&#W8T!-@1S%Y^msjSp(rA2RLOHC+Vmc!m4O{=ln$8Yq zV}CCMH95n;?_roVlwd`wxb-iII09v?&H7_TpQpbe?6tPNKh|ST;L#yFr?n3HE|_I8 z?}`M(#Ap|g_v99hPLZ0?7u;L#!>^-z@%kTYfoXa1qXzLKKSRSGex&qx0K;n?rXH;i zX7qBZ)*8hsB=n!vvO!lR@y)854fXL|XOXGpI{UIY`$7C_$~Q$M|65QON7xSRa{nDT^~!bMi#7WuI7~#Fn{9JiO;b{_+H9^9 z2NNRKr=Ewqt`2kfj%@FYFt*;nY*d5l>du09cprYBlkEVuJa9t`?OZ2Ri4+1Sar zpDtsokwyWBZ0#$8xP~DNGqM5i(TP}CQi2zq58sWlm=#=XSe-u*wh1nd^jv)1J*zRa zOYFI)%^46SCMiVyYMc)SPU~0#xL<9~FFLwJtI8p+j~?J(?CMz4CcJIeJ7iw6zYv&Q zGLnzU3GS<}n4OJ3ZdQ$MIydW4s$X+o$-~H=9;MQ*Xez18PjFW4?0mA_b)swEr0z`Y z_WHSxPAcW^wz(D(Gk-y(#Q$D-eoTIsB(^pReYUX!6md!2)C=ClyCFl2~DC0JH$HPT-Q8~Fvo_;VRM4DmSFx@H;Pf^j~0nT zTl^|n;T^#2l2vazTZyY0MBn=4q?}F^Onm!SS;9_E>`h@$u;OIRU9tGF)Y1Pj*jwnZ z!o|YY(yH96D1V5jniVu}_ETbh$h6n*Rn7Rwd17k;cSSx$ z4zW;3+cBn~>-T!m(16#oik{Ls*jZ(L+j)}U+#G3R` z@oUAlHQ*aK0)?Kr&b(;+_UlZ9YB-maSX0DjEdUU77#D4$>Z@%#CH7d&Rsp_#1^(la zC<%Bsc!1|7cq@tY_+C|le!U>{&f}xJo-$~qBq8U%VNq>*JP)YX2IwxrP zJY4brHu%NIL4?93a_JIF1pCs@*0`xkO@aj65tN0m zF5ixG-8B`Cs+W|MoVa|*Amt{^(6T{Gdqo>%qPu-`7&e}~&e$?HD%K3^#Yxkwzu2V^ zZj60Cn6qh`W&J**AC8`e`HBEj5}kSh3&qJ=%6T&9sRaTv!V4hvb@H&TK{eR~Vc_Ob zqFFcKzTf5f4|;VZLn5?pj#wW>r1|;B=jhJ;kHMtxxpWsVJAK(@XYjkt6KV z_Y%OPO1GlG{%a8=t<`$&tb0wxRk*0 zXq~s&HGHzem3y3RSpjpdPB~_{k)= z_S=CN{L{b3fOdH$A~9s^zOl zAx7XGNUb38tfR)^BP%^B!ifQ5Fjb91=fDFY&LuA@^kj|)DZcS{{?%6c5h}cEK7)$Q z8T?}}hOsTktGC`oh`SRFHY#?*?WM6jO?Giu!@dd;l zz4(uk(Fa}9+o8=EY?<0_+ZBLrxGS7hvtcSMDx*1(oY*i5_cIcH4)ljvZvp}Vc_zsN ze)B}`_?vXmy`ddaKc*q)tq{(L;NKT;yIC)Z4*D=9y&}cFB2(#tmQP(=GeJ6BZ<@6=(+v~txjE`=UT z!YSp2)TpQxZ*F-F8_ay_sypfkn_|G$u?H>0K_Bp;1#5)MT%3S(i}`3wus!jYM*Y=1 zDBU=i6OhrzGui)zvGdwT2a1;+`)bxrjqp2<$~BGDRsPM#H-)86jrt#_?!Q!u4nC_g zmNnAYM7^tXUPLy|-x3PtXz9Q|aee|0dv+5)!JTpEhSu{d0=5>3P;yRM1;{zhB%1lo zudN>8X7dF1>VnnXr@gTaC1SB2McU3c!s4Au4BDyiYPE?f9QAo6v=IWofgFo;8JnjZ zG?5!Ugoc(>fGbG>#CA}}?sd9tD}SlahDcuv-R7C3(KOxWx9<7B61zEcLEuMEgXVUy z4@|bV+6vYRk>8a0z(CNXlI-GQ|FP(E9COXeNZjxNTIuf(-EvA8B-ZTtbJ{M0yoLCR zeSu^SQ?>JdG#xg#fs5q%3Qn%3eB-iXJ}e6l;V{8=!Q%!WjaXe$$v45Cm(j;Qq4fxV zAA6M=z$U>JoCaVt?|U#AGl!6P?@Jpyd@!o4BPX`ie)2Z5R{#x~)RG>;+tTyzgF?f! zS*{+B{>1KhWr2F%RPt?eEqM@Nt+`pZqN(P++VQ-+B|eqQU3zte!SpzVorx@Wl#1b| z-F~sOLv{cam|DbD8LKBdGHZLQrCcqkxP%UI?ri!MI3zKnqpIo1>XFc zCGWx^^j%ZB`aSXnaFFL6mq;4|@l!F}HIo`xt{Zfe_4k%5*dFy_v9k5JM*kgv^Ew#_-&k)Pw6rR62dLC zjBi3Tlo1mZtJSH`p7&_!;kT}nmq@3{b|=S*NNefB;mUj{U;Fx&~8UU+g###-QcDsnVphM2S-o>KJ=yYXK%J4j zfrl`m)#NM9Ug#M68%b*`c#4)FIXuEjWC6gPEA4H$%jJ~txO@+p*W z!j)3&@*(ga-S>W#Z#CtS-}r)d;T|$NB%e;h3IA`2?uj8=y0S5yySO>D`R?6$w?=kV zaEf7R)g`DpijyX%ERUP$(QFp~CS z)z|32Im8Fu_xuK9V$lT8+ixN`V@Gi&!A0+5a3jpZ>up^@U(BB10#K~NQ>^d==@X|t z*7>}~Bk%=@MkS403Tghl5?R++Q{E_kc?ARZ7V= z!IJH+22O!%p6kkQYIPQBd_bgFwLHOV22kO2_j}7R?SBl8zXor89f-lM^0t9&isSiQ z`#6iOQejKH@_DUg% z&s5?@7)=uLxlaO)iM>x_%Ftscjrm}H$bRM*rojatfHu^mG+OY#VI15;mwbQZYrA{v zew);Z8jzwWfk#l!-s?1FMO_tbYrP&7LJhoLfQGNY8a>a~)jpX^S`htWb;OUyj-qWe z6W)hyYD&%;Xf^yaZcRGTok|V-1PZjyQEE#%Kg0yPoE{RX{Pd!h&+BP>`U|FWJ-OB5 z+wP|4WL0GKTzs`Bjq3&`G_PpM_O>J*B(k_c=~Q1!(5*)9GYHa)00pl0 zYKZIz16^azyA&XGGfh#_$1Z8|s~UdP(7U-W6{x{1kJfrR0SM=k_*m7>K0BwxCjK$a z&wb6Bb#whnr%j|&mA%E>#exE#?kr;z|xZXZRA}sJu6@MQqLTaBy-Sg-lPJ7$p_g;}d@|D0# zTFx^0G3(Hmwou-JZ>vkoukYW6$rfwEEEHX({3V7#xjUWKlB-NNHw3lvVq2Oedi_8` z`^-oh@x{u3}h8AkynC%X0=1%-x$?y9Lhe^~&j?B3}~{EOgwHEg?q4WOVJQBFsGY zzDz}in)b9OG2Eg)5F~qa`e-FnXnx}J)NvpwCA(#?3E|3JH5U=vZYFHduKIf6oSzsq{iNz0Vh{$gaHJpr@EwVX)G5Zy0uMl;djRlrTKjvFu^gTOCzl6w{k$N-||~H zp#F-vZ5rji3`%Yi&@QCkI+l$JRDx(ec`3&(W?$9GwRS2;ygPZAZH;ZGIroV)?e!=W z4X*N~8d>ABQf za9pVNj4+kMfSVqH*&`c#BzjJTOeBOJ%AQ@1m}5_=?dBz9Ox4*%+CY}{1lE5*og!)g zq8!i|T~ig6A8qu8#b&MEs4=X)7vKsBGmdqfj8At8l)Xv#?$Q2$Sv&u1P)+Q8-ZLO* z3MThI1|zdb`QT~1pUd{NEi*Uk3(|ONOS;qS6+zszzGS}wxwT@!n)#Jqf*gi+)s7@s zsyEPI6f4&{h8j=nfjWn|5o!qrb#Uvfd&R};sPKjrRm|xO`{{g=S{OV%MD|52uAM$DjEJNJIX zwCuJ`Sl>@})0^Ef%B?2Z@J$+KzB%sa89?_xHJVcs$k(td%Xd{3T8>azO}{~WEs5xu zP+Z?#IB?@mVpI8j?^Z&m6~3;w+GYzhqO{oDA<;Lbd%f-g$n&%0BmgFXXScXm6$bQ& zy;fJb6cI74*9w(myJl;#xj5NFYXRoIc6tcP`u}?Y_V_fNyjV#YEVoKlo{hkVtAAlG zMTPJD)!P4iiD^$=syy4iz54A{yde3|UyN5H^Tf#Q_)hRn>y>PJ z(rfViDFtkEtFx4L>4Tm1=iH#Tg?ivC<;){13!>Ih{P7pJ!oB9t(If+(NZnP{1>=C# z4RYrhauUvpdF&UsA|WmRlEfCDyehIT&d3^_# zbu!x-D;7Qx<3C}dx!}&?Vq@c}~WMI}-Qi zBtH}s(QU}`!b02}R{qI4`fVl^d3&RH>GpEj-lN;8UyOs-8-i8!rbiU_$^w2P2X=Xz zj4doIDKz5@1}2fTD34y|{^^E!S9&>G6Q=}7_KYdU`J zT|ri>4QM|pnhg!xiLu@2UQ-owJF0QmTi5_JPAhE9lRQ_n?g|veb;QV)Z9xLIT@gtN zF)Wl*PWGU-3A4`K(WGp<-5nDpG43g`c&DnJVV!m4RNzxn23RQ9TtIV^0pkAZuVU2o zBj0m?IrReMw--;R_bvGbxj<-2JEB;+TIsXn_SKi(g4R_rI}P(lo|jj$lFh&_AqV5} z2!_7chJ)bmuS|@_O&Z!1?an~w0RBPaQ zzWNtn`SJotnRLMw^6zf35UO&cFWZt<#GK9=>T+r~yJLFE(HosGR^A3AJsjAEuVdB>WjY+1i499ZN zWlmP>7CotxNi|qxQd0yGZAn=<4R@fVA?$m*G1}F=7M&?6>O0j@b(s(Gh-pAeRK8d7 z`H8nW?lpmD>i;M>_irW~$Nv+Nd%5KvDfipVFtB+f#;8p^LU=;InPVM&KGcWdq`1Ip2$IQlSYMkOLcbX z!kJHHarnx7Y77O(j}7!MWdS#pJE|$ws_ZlYZ!!rxtycg-%;iBhayI(9CAmV%`Are| zzBg378JKYCZw0SJ66+kvMa)3saq^rhur7&>zSNcFVotkiQtadc1q0M*R@gqYT=~Id zd1g(0YH{B&T&hKMEq`!RXfD1_!7y;)NXL3VFoH`XCdODzBrEW{je`676h2S~8z`H% z4%d52D=Fo7?Hn=bA1udsE5OSFIQ2=e+aVF{NrQUrRx_mDTzs=@0jDqnQb4cUg1yXi z^)XmMhgspCQp6BsA?pBYDguKM8k+qq4y{S%Z;(#02d=^upAG{m1q9faBm`57anwet z&tHZGtH*Ai?oB@;uhbI~O8pp$dhh(i?OX=MMn-Zh>Z>SaKI*y{rSsNNi0ak4I^tdK zDxrUR&mvXg!10gFiIPoU01Zw%@ba{~BI}22rAV2e+Wt07#f^WWd$&Y-g%Y!6A_x zk(Z5GQtVHIIh!?Fe0>NrlHN3wbD6cxv=DE83eRjF!$etBtq4rh=Z^1m_S&mB3jyHY zuwSQ-#aXU!Zy|F36oGn~_5Cbxj&6Z*^LIvpg42zc#Jhk=y|e9`q`e9|=aD6HrP{w| z)_MXI>xFn;lFFx8MAaTX%U_0wy5lM(g^sP}G=SaoQ{#Pm#@8Gl-X1bRIr62>ig?9M zt+yu~8O-FY-XEAn$R}+;UC!+WsbWsLx^m~Y?7YI-0|zsxbHa-v)YJc?17`d~0yg@W zVoR2SX}z%@QI!Cej)Kczb(zd-9}wMOAM~T6aE5Y2)uNt?(2y_+N$azURY0Gf8786Wgd#hC7r^ z0KZ-`zb9aay#iAte~R+dTo2K1K5(zJUA0YsMe;dL#AK3NwHqH2$@ymN%NIq{Zfm7g zGJ&4BRn?e%w-pr=gjJwkao2}%o4x;|b4gX`Tv)Y?xK`F2v!t!U*;SB$!1p{Nx`3sV z70Go?KD_LUgB3dVi+Zr8j;jk`^aJn|;iM49J=L&)KgAHfSok;e^J0vUSff9BIWBP@ zrRSd^k`A}NeI_pc&YOMj2@~yA@_7|7upsx+ZV`{MXm~akGqm{DZlmh8DyKzok>gBr zuyO?G>Pl`>yg0QEpq_c;@!%0rMN;ESUDZ5(`!8qof5VG6>smik-p~ON0nSS*ma;U@ zX~vBN)Gfd?YnJT!iVDEpVp|Q|aG#>1YKvIcac^3C=0SkzcLU!=zk`dpcL==`B=oW) z-Pm0{tc&q4qUH)N49B|rwPnuV8*LH4+&^$#<_}3DF?~y#1&6MMv^8!3q}f4G!KUn& zfKRmo7VFO??(cyQwO=chAZ}zl2saevWxpHo1xC1c_hJL-be6p0a61gXxZnr(->$mh zgsV!+^V*Bq_AWn|`Y|j=d$n9SQzVx!IjPq>1osAPlVj$yA!gyg1$Tp*|0Y)|=VdRj zG+%X4a|jL5{;QVcZLDsm3XxI3cF<9?&T6NdB86+Bc+_nvDD<8ne?Z&P_j^E6j?UJa z$WeccZjFd*dse7LfYUnxNoh;bN7N{DIz|WOQTmN za>d$eoA?GlD=N1xa8d|@31Y`M9)J@9vwU{!mv8*_zoxTg(pDL!Cx{qf#hB( zU)FKhkvDkDO!rC7;mNLZtF3dmt~*ELW6j{LH`G!t7ump6m8$Vn-DXyzG;{y`v7gm% z^FO>|4q5J2y28mlZ5y$fmL_&1zyQPBKW6^0`nGD2{h553_D$n(Q0~RH$TG?7=~9d` zmiwiQw zAt+3Rd%GYHX5+AMP9cggrHvu+OEWKEftYQ3@#rYh9~I?H(9lBNbpGscr}Tch%U~v< zaUp?X!GeCPmJJXT?A<8{w;}(e{-(8=Vv$?_h z=>1mZxBkvzM=+(r&1>P9fm?=$fzE3;z4j%g7KRo-lz&Al0!c~i=?2*gmY5Nl4U{#l zfyX-M)JNp-B0YR!TVAx^u=g9Mg+-ef>C%6?Ng?k*mbT;$T&Zm#hqk|X`8t12bmq@G`uaiIKd{rf*^)~u z1={mrY8Qz+){_1JCUy^xEIlAt_?hS+t4+dxcVz8TgCpw6`zgf6%YN6s)ckE;w4)jV z-`)7#e0zwP2=2#5U?T)sTy_%U#>0$KWYbo(IlWpkLuGP{AC@xlD ztb@Vi5U4>>H9!-2+$2iHnMXrdXyx4V1DyZ|y0cZk0Av#0CpW?LN(2B$vlwqkPd z?+Ub`pNeY97ea3WJ3F<-OtV(vBh>FJ_?Z4~PQn=LO zK0kB*26d?>+iVkS7L2U9Si-W-C8oUlii#?YLkyA30Jr`0doD4D@>x7aV5}c_$)7qi z_<`o@ytUJWC$({$L6!aS$w}W%e}B>UcGg5ie2F));fwSYj?|W>x0Go;l44MZD_s#} zDDr-WhXuoz;svC`!&x>c^D(Og%H}no8%`G?jVrd>8>YHEIeIZzKzfIgu9U|EYrxXj zlg1>8o|pAZhO7^Do`k8e(mU5qgLW~&OEVL=ADL*^v^gu3bt|o6e4W6f{-qvyb8ZhoXckG zKPYDAf!myDj*;&_S!Ulj9p|YCjR3Yt=XIEImo$1$B+gQA6T_?c`DEMyswF=sCadUz z4@xcjyPt~@?j02Tv4Z-uXNUQ>hgET46Yul&7%MRJp13Ttn*ujCM%V* zasNkGBs+h#z6;u>emHQjriYFx=|{u3l$%0qUTEH{Ny-_~-_QAM>F;&`t=*1XjcE@j zX85&y6m;i+-)hrY5yL&cO9M7$hga%qx0ttjXw-Am?N!S3F!TLO22<_um&%dTJ!;-| zFSys%W^pWELsSU7LQv=0 z+7-9qu^54$c6LeQbSZxQBl{%}V%I@y>|G!zQ zXU3bF-Ep*DE&I+ZJ_PJg-AnOp$#~hP70FpWt!lv zcz321PNsJ#T5Uf_RLIV>ls{rFDbwYC5Nbk{)1vl%z<-OGP(X@Rxx;l;mcjK(@P3A0 zyh($#|H#8Hj07di1#`WIs&_(lO3&`cIG4mZRcgcrPJiEomNeSt&=qv|N*!2bG-V3$ zPI{=Q*XKHV=o|p~|9W&-vA&vy?6+dKg-wSmSWu?rkZ#485TIW;jv}`};(%JP z{X!|;sJn`Oa%IryG&ZpFri1=KBIbFhksZQYtu)jy$RZDe9OeSNmMSj=LG@`6OQ?h}z6mN0M&5Fk zQMu1n=V!r_#6wzJKJmBWL=vAfXc)z7c-eG6U6#!`)nxxN7Z+y@{`rD4g!XAO7UUFK zws&z$8sKU4`AM@V&+BuejCC;eUe$>R^+i`~ovH*S^ z6Eq-3N;UXZAD!uK6pbM7CE2a1v=me?J%q^otXL{vUp#QwDZP*LBaQF3ST^t+4A}VD zQ>wawvj2hr#NK+P4R-8H9rfP53yNQxsXtTUCiql5=Bhe%5;!vHC&#OfFb4e?XwpFH zttC_!j+mJ+r+r~}=Y~KCHxxzXOa7v51ns(kprOL)U#tr$23`uDf}7zr_nWx=;I4Th z#uM3xZ6#N7?CORLq!Y7QtNDv+6xmb>vUTsyH|{=dD?C69e}B4@4CY0cXENO$p#m{NUL3fK+tzsvb&;QCuU=Ersby;{Rspz@f0{ekbGqT~-5(To_V}L=igF$T z+bl`m_2=}t?J0d7^(>`TapI4_Lh;~|NZ3Ug`Fr41TCCB{xkD5p&sSP8eyC-$^Kl)?gnZhuww^?Iq_HD#J{c?7$rK2;@=LR^Wu@jut(Bq z@|Zy_E8*KXC}+rTfWE7Ex$Kzqo^#l`>I`WK)RwWPS=RY?t_3X3re>e>Y9@YiM zd(Jz4cncTXdc~E%!=TkTy}zUuRR=_Dowe~}ry1K%l-0IEz4NKatVO{{=r~A6XdvB> zS@B334yk(D&8L37e#s742qwZ8h?S-*^&D^foa%s(8yY^)_0b9p&ifpnnscIjS^b=b)lRJiUC&ZW2{q*|%_p{4u>ESTIO zaj9^g_xyFK&UF7UtLOjG8Hbz8iKZ?We^A7_D_nwTv2PBZ3~KhGcn{!rEoe9grl*FP z|I=+dE2!EX`l?r7@S6#{i4=k5fEn3hk8k{%tyZF23WFFk|#nZ;_Ssac{Z+Zp=IF`;3eKrBV>o8@q52ubj)I zWv0ucIT(=d*xS`PoVAE#X+~L+6>|5vjL0yfJLbsS;eE9N?a1CSG@z=R4y_Q-=1R|& zDReh5#lF}DNEwuRpo&8`k#thpTT=loka7anDA^yrn>tIW2U2vTNX+l-|O zn<7-o?NAn9pmgLSrby;VX16Xp^$migSAwyP=bzv&dwbUnqXr@RnTeCornH-V%Gaja z{7-P{GN&u-ZuH*H<7g(Y3j)Z0y>7QLtG$j}#&Qa@sB`+ig1v%I;&|ON5y*HAn};vs zmvg=E6C;g`LrG8k?iw!8cGXpHH-lxJhs?$<`vd+wh$+mw zck|}rRa9@$s*7@dWZkUu;7nCcL4%6#4|`~vm@1=(FvKi=b~pUdfx@@=0Gz4FcU3vZ z;~+R<#_W<&H;;;nP>orS&bwHEv661(%UpC>rmx(yyys^xQXS&}4mZydnceaF{jv3^ z0nzqt>F*_IWRa!>w|`C1Z^%CU3V5j3<}Ud&2mIio0)EPAalLa6>GdbiPQcPN{+=J+#l2wuB!Ic> zUpW_RIRIo2&mRCEH49}oc1v%=B$(Ba%T3L4A2sbh2))-g#m>xlGV!!zMBHh5`ZPfx z-Xof@?dIoGJ1#Cba9txq z6TC<#)$Q$0j|yi@StiN$UM)@GJYy(x8R8loFN^en=Nb9Sms)vmk~o3Uvwdr1)$iwf;h`4=6$UT# zORJw-9K#v~8DvZH1{!}U<1qe_1!z`+?;l}oa!ajSmk+s0^2_g#l+?vY_TzGyvoO)O z!qs){4mt&?J$Tmz7Ly3Ksc4Et6O9{RE<;{(AA(rS33HWDse_xSq6U-9*H>gjtZxKm z_@_=WFcKkDP+J5O_lipW&Ddf($&6Dyw^W|{Zk=sUmb7)3tRjm*{pVx)UIX)sH0vI4 zcPF#x0?BX#pODSQC_wa}zk}Usi5VKacDk?Dm27YGaz1{k;onO9P6%_?4-2gO^98d_BO+?#I>XFds-A z%$_NwzGaxU-AxUfzo~AGqufJ039{H-8?|zqc+AkT z;Tp$P^dF9P7)SKi&Y4#=f@ldGp7wd2jRg|e(O{06u!(p@F|>6aM04I!K2w#YwN|aq z)hSjdsBj$Jv{B-HKM^7+v|ztJZ~NMQrLbfy{_$y{07!J%NqRc@SSS6eq{w!c@Qrbm z+kX{#+;%-P({a~ANNJlz#d$R2Po^zMoZa>$0|2H~XVfJ~tlEng51VswCmXwJWio@5 zA~@KtyI}p72+5P%ydM{MmQZcr!M2;h8{k>$^Y(^Sy2RaAZRDu*Tm=4r?#pkgIolha7EGQPW4pIj6z+sn=&)r z0j~ydh%iBJE54|f%G^JF0sjYE52sd6&YMktm>zaI?s#|RexjJ$QesaoXDAKv1DWQk z^K;Th)I5n@3t`a<$w_MpTaGwss}@MEirJY%g+47kF=PI!FG=~WYjR-^HCR_l66elb!&?O9L zo*zApws!pnXhg}yZGxJ(<}o24J+NMz$CJO1+o6ay4xfKu?;(VDiD3M#g@xavCi_1I zX^7g2NRdWjpKi^6|d#yo;4rX58*h0EnX z8X9UE4o?MgxYJBP9qdpY4w-zlACvc5*nm$XU@}Yew^68Yw;;vFnXuA>JhSopoQymIpZ7=B>+Q%BfgWV+Xmr2akoW7;svq;IDwDD?n? zcF|f;<+s=Blgy8iKk9%4s9v9q%sE!NMz=E!mA6rm8O*u z$a23tSLscW12sqGN%uX?7H_2p(9%njO?xe=ee;@~l0mCSt^Zw9&b@(LRdo9iwo$6{ z2J%3Yb6+7Nq83r2(Ht!s62>Tv6idDyY6tG=%})>kiQ_7IL8=OK=x%G=f2RN9Qki0` z+P*tx)gY?!1%(}sO*C42WHUJ%e?`J+Sro~F!<$ZY-E1xQ%0AXX>uZU!n0hOYTAMw!F~r0F-6n~E>C-yv`7L!W?p@#O4#O=EfKG0Na|NP`NUmwe?9qH*o?R2 z{SRMCVbSX0!;20NxtDTPpTF*4%nc9fLKqg6EGxB?zApB538LYqT(z>AU2|J_q$J0U zHnZMz$PCHl^uRr{AerS4SkYrcGsjbNCky&bDoJX6=S!J-)4TH6`7P=dLuq*x}G}o8O^}G8Voh=H+xRH9UVE|Naq7B zxL5^2BjdB?ndF&TbtB} zo$n^u&l_=Q!2fmc`^*do9wL#Q7=!sP#w+9m-2Aj&&7QHwNS!y+e7&OTx@I#;#8rvma@) zGfp<10+w75G`V1qRIUyncdgh&eoP8aIi-$7EG#vS=^a3W_;o-IR7#FcHFbf zMR(ipL6>UAwm9BcyD(Dkcw*bsPc4n*;ZL1_#;1>Z_TTKGT<=m_$?TlYCv-*P7Q0rv zFjPm3q>wZCpFEpfH! zH;?q6+Mk(+yIwDa&cBU1n-qi^Yw!5A%rnerCLd`d8FGUTJfjcDqs7*(w20sDxn$!y zV>cJ#j`imL_80_2)$RDvXuw*RSm0u&nbhvxv}xC)QH2x1!^o1ASXACY`A0b6>l-5{ zb_%Tbvb`usU9sd*3bsO1CF%k2p>AVJFp>xVVE7he47oI2WHQcOMlQmpK=}G7Qa3GW zI=5Fwl9?fS8+s$Q-12ff!O73XK5xcq6;!S&u;+*9Gf zpx3Xsdq*JG)r}9zeIgSdNKrAbdi1xii~$vC4m){Rp>KGDw*lowz-abBsA0%kMadDh z{f13&3O_?(MQuW1*1-UQtI021rP4IBwi$@~@1$KJ#$u~#^{GupB%7A_{%jH6G6SMN z9Wmms2CV+ZAO~AY0mX?cNWbO~RU!|mP@DNZh%N{B6sGe@m-B{)-v%@PJg#gztKziC z7R%=+jhmhOQQRM&WLaEuq#cUpwy^*Aua`$CZC=)Mr@Z$VnmLFzfUPC3$8|A?`)I4Z z!dEVl(Q_#ZUT+JEI-5R-!7J{J!uLgIw>=a;0(8!c9hCC2d#fKl7FR(1FMydZrbnZ$ zT>A8uvBFDBMUEXIHJKQxJr^;t?I@cMQuh6ProX*!;QT#5JBL>;e2kn9p-uaYhP)P_ z1d+pExGi}Rs1G~w81Izn3lgI^#ntcToIE>l-kn8wd|8CTn2)5s=R^4SSJ4;6!W_4 z>`QRPRMj>jfpS$cvDd!XbSlK>a_C{S*ceow!oZ7caMFIsjPHA61f{-P zfCtyGHB++Tx1w?v_|O;z1j?r!A6e`bPR2JyR%7iFb*BGl5}&1&1MxA;dZB+nXL>tm zsneTg?scDZ*jL`#7S-O)e@H4CV7R_9kc-NnoaJ;-rA_xbOwKr#9|yu)!sj*MNmxwg z+cq!soc8L%AuFG*i7x zh~CpNImG1kaj>M?l6dh(*^H5Q%1p7P#SehyMVzxvcyM5`-7ibtGvo}zbVw1?Yt>qe zTm8OAqkdSSYNb}cqyRlY!oToylGoz$aUhwvEgqKM72t%i@DV9T-vaKW_p5s*xmPSW zPdLSrwa!Z8)mDwM>EVx#0ytQCPNU471VD;?);Z+J8bxCkediitF8%!d&TX?Rf{PQ{ zv!_S5mD8qfv{bU8l1cdgon*;o(KqCjZA#A5#C$9CZ1?$Gj|t2}!`+(i*<086vUIg)11q zZ+)f1t)8_<2H{cE7pe6xZKA#RrrLt)J_t70irR=U`TJjshp_G{-WF`#_5mM5xG{S& z-<{3s{E7{$e4qPa-#+wT>~EAQidiRC&nm*}(x|3ikj=wCc9yk6V;*fgDJ-lrYZvUa zNJMDfTl|bSzCw^10HY5JH;!MN{JSc+`I&bqg()>8h4@g&C@U4z^v=2UP3GG>8SU+NqHk)#16P=Q=#PRLFg>){BSRbZ zMy4x*ej5RKs6w6t;0rrU>2|M4<1ed%h;l44K(I+}EQg&4ue|YFV6o%TJn~DyMVF|d z0~)b7dYoknZWqv##OcN2k|-1&(l2$UOPlei4)cQAjkbA?Uz>lKokhI2`% zaubuqX)n#p+_dzJI=t}vz4^C})`*p zlmh>5(}0Wby3%55>7Xv7=84B#K z&2pAzdE9#FZPVD$rf!&V$$!OCrcUYM7sOBE!4?`3JfY=IDPD!?@S&~MB&O~Qb>>7$ zmIgTZvOg)*QZYYZDRZjU85nLSF%lE!RQjxrp^bB2UsdlqdgxBb{#2e9Sqjcz+gUXX z$ZU>$Z(iMh9jB8*U=)M8cnT^PDt%|?xC&_f?a!OnZ5mNklCtqqB_(D;Z7XScK}F~I z#%KyXc9Bi)GGp>9|J43{R?7eeylZYn+SWT#alEip^+~~;BR&5?*mIRt)7;U5ckNRB zF!rlU<3W|BoKG|M`hkB<_sd1UeHMeQ7}kF)LYI=|TJlkQgxb`((*-l(Y+Cjn!$&ME z?jRc)JqcJc_vVgsJ_|WQyp8EGHLbVWyi|5kRxqO?wkfEttP=`97BMgXtVbK#ulgIt zC7(IkLOwGuvY&bUp*-MHcerUxfz;4|@_E@uEr07Yh>7U?RR!UX{Z#es&KkKSe}aNV z^SU?-ddUT`vkm-fr=%W;n7T;Bla9n9}X@X*o7bcV9xa)QzIrO{-m^hoTm^_0meT z_q7PdA}w=6rE0$5;Dz-^EHZQ$4_?61#GacJ>A)1`YF%RdSGH~TTr`5t1G2cf;=Y7r)FP#Pn^qtX z-q}1MXkOwVy@@_#=O#_3od{ETpCkid6}_00pVOweaR8>k4{wRdy4uF7E9-Wv968dTGY2f#4$Zgvs@v)A(Ay8lopGs*`s~=P z;#w{I8qanM7>W-!CwZHV$PK1eC9B`8_ZM?rICu@Xj?vLy-MW+~DX@%5!B8wH3k)zV zUX1W}hx=l_k#NLN{1M_9acjfsx@Lc8n-f^Ejxg(?U}|39vZ$)rh@zr;D>4r3x`oz> z52Whb%oWP;N&{AsPR=A~3t;G>#XhKURLPQ&kT>t-yWY01LrG%fv^C*xMI5A33^PMr zVTN!*>rQb`%SPDZ7Zv~6FAQ?dvW2=y`J0ML?2p~hUL$mvtSv9A6tz8sx%MaKGsK6- z@6BuZuZ3GC^wJwxtZi-bflCx0R#-6e{_(p-K_e+NUb&fQ$C#@*7TsIqjhklZ*cjgV zY_l0lI&ZF^_S+Zfr?ny!t+pVM;SAD{uhK7>A0+Y@7FP?%eOZe*QlO>{xpPq-X^s%e zZPbZw!-E^jV6{!uiWhcquPXeJ?wAu2C?uv=zQ_ps$^2f0!+}LXycTA|qr$LgV;bnR zkoHk^IQma$(@vC5{Y;;V0wkk^7p+r3KsEeNfwv=1WH3`bfW zJu%Ko%0mo27ret4QK_*tB7%?XA!65Z| zydV`ruK92BJ~eN$f72q=1mGL&GeJt??rq0Ns*}2bEZ6bLu3BNPT94N37r&jnBL*S7 z!L#p*_1ik=l9lmwfCK#H#-}&dD(BF(N zdD}v?ub-&deY}CtAPT6;q3IEmc%&0=F^wkgULX73G#UN-w?F)%S`f$!ab z-Chq;s&yq~`aPUYU*2#GuXwU@Vm9GoJ>@D0vqx*ZJH7c~K>Xk1`-SJ!8qEdOKyMmEKh10FSzQc9&^am+0v zdq<7@Kbe9#jPjB4r71jMtw_O*5STCqN$gpFN$3jc$k$ey0mMBkx}?vGgS(3mvK!Q_ z%hx_x0{AsbGT5*?uX$$}ZtSF{Xg&C`*5?!}OU}`6$-VZx5-DIUcyS_m{IW`3L$G#n zi99A!h&7ZveRR#V3^3^ySo*6>ykzyV#wk^; zI*TQP8qqUfDz*Xd=G^J?g9Ckxi52#thkxN1{%O678C>hQr!yr1>B(bQ@dI32JO~oKr8`sb#%)KLhupJEfZD z^aW3BO(cbThd`!ZG|DCA!$;9#p4}RY#a0u#?1Y}TKXlD2q{;Q(F9}hQwE!yM6QErtzgqLO@!PA3-*a1$o8CT#=np-7S@b6k=$l zrDjmwtX4OpfWCrk<@Q$8wKL#@>qQ}Fjt|li*kJ!dNnW0b1xfLc93yZ9-o@m(h|MucF& zSA2N6FO!uAm4DL{47~GSX&>q{UtHxD3>rA&Zu()6@PSo`RU=Ho)d^f?VjBr>DmP$# z`)yPPZ(6(7LWVLjvEH&q9WGa44F2lpt8B#`T(=4Fjb_e-#(WztfufFLtY~jrHkVxH zIqNcs$4&|^eGa7Z8ivG#Qdw&GZu#9$mQoF0uZKG+x*KL# z#2}N%R4thRFPl*MMNnks4*_+%Zo1S$$s=+_7C5~I{arG~{E_AKbSy{kVu$H^mFiTj zgT-k|k?@$A4` z+M-U)Aos_iL8a<8Ud%R%3T_#aq4lb(pcuEU6&<-+i17^42j+IS^{2Bl*fRvdh$VE( z)s+9iWP^V(8}5;RKthWMBrHf8r%k6=C9A`IB(@>a_|y0I#+_=9{`C6Fvd&2kAEL7i z_|+3uysxC<9f|LT`5Gjpv(t%R618vPVL=%k*;5y9mE4caLC3x$TCM&I^#0QU8uWQT zq18c{ttPZ})e(FILbNHb9MR|VuWXf% zV#@pjpuwrc7<2r9rVJgy<%Nt zisp6Cohwm4^#&T)`Z=z<)F1-j)_k6hcQHUIHS=5~7;=@$J?*$V?GW$Uw85akth$qi z%@>~zUl|glm^a)`Nv4=d&PwE6fE)Zbl5J{c35K3E1B`*-7VE%`#6%?tZ$}+j+l%$` zwK<9|t57D?tb0qxYlUQY&=w?-bz@2jh}_BW+(~>eSiW?qtL`X8jc6o&8_p%ETar0U zMIhqn<$rNR(n-%J6Jm@URCqoy?dKb6Opg^6g1$#4$UNuqr24T9vq^!vXaf^u-I)G` zfovl#=c%1~QU78IsonmD8&y${@&3Upm53Z-`Bs@GJD=47#Nz#uajs4yjX}e|T^_0M zglUK+MFDD}w%Anxmda*g3Gq?tNb*zTT|j-e^alQ_f5r}rmKgT;eegPR7$FH*q-^s#mOy68d9qqPXQgrgEjBwe{l!n^-F{-=@ z4h->>D>D?mj=o^84VOsk%=+MO8UPoJGbDxT&jcH5RHsp;=M_Snk6h@SmaWwkMIP}R zUXl3l_?vsEzY9TG!htnNLZCRUyi;(gAB;08^sec5buxSQd8TIXMjIprRfIv)SwfPx zpeFth)w1%^9ih6@kX+2jR>FZ0;o;}=`s2ii@*#JY#_M^rvnI0IZ#2io{mPskb^zq& z8ywKHe}fb6>(tZ1Pk>oRT@d9E0=L?=HO6UaK841B$t$$#g+8_k4P!*h@*>K_X*&?GJxUbFTez|NFA} zvn|ga;!UMyr6A$O)t%*t+w38B)eCufN(Rj&i3Gqo?n?ZhKIq5!^Bk~sr&q`1U~r~_ZFY3DwVv04519Sx=wy;vgH_tswPl`J&`?ed-9lb-Hhxv>36oI zo*EkMx!&GbHS8lSyz}gCPY|6lzfK#{II?nlC7Y&3sY*q+pkw^(TbNFzTm5{!xqXauM6KLm&USSH0>iE$Q;`>vfWOrd>I0{`#NIzv*ATy%tj$ zyPz){c{A$UzBzQXx^%u=VePzf3~pq3&kssjQ5aye#N<9}+ZM)M;l6)ErD-8sjo&<^ zSB*_$rsDpG26q@E%p`ng8|@iB&87NGbz!t4k#yZ<)xwG0PuJ_Rfh%<$WST3sG8kT@ zoOL68V+iZ^c_q#4%Q!G?st#^ZWvUhQWa}1iO1do9q>9+N{Lf|}XYl=|?QcNlhiMPW z`$5{)AxCT?g#|KGsZ#SoYKrubcw0L4?fTy*^DY(EXVr5{tR&K=yTP~!xdgL-SX9`sk)%;tU6+oLC}PN&xranZly-$N;2*;3v}rGs-M9&lRyM>m$$RF>Kt~t*(0hNhZsH+7F+@r7F6aI}M6xq56KA>hCHn-Pxp~T$kYC zFK!R|brw-91`9cB*YBxtzkBd`;jIGi@7+y7tM0oVJ4lJJowTmqOFL=8O&BNb^PIO zhTWr>SXl(Bdgg`&plpNFDEqiY?P@;Ma15krS5T8Ec5p8VP@?|-IdCNkAwb5 z5A*MvWev@xrX<5shzN#yFqfO1GvvpRB+44@Er0_=Ds-y6K#R$5x6Kh%298M%fHLPsqRh4CCMu4=k~k=;#Kc!Yh;h!h=lLA0P8fIDW2fxIvX{ zylcBkKeN_501~&@egZ)Usb6R#SN@$ z>V(yr(7nhX7{t%v`toItiQs}sAx4u`h9Q` z`_aFKJKxaauNd%FEXEaJo9&g>(pc68v3fU^SNgOT8)zXN{NXr8sq-XH6QF|J;tZG8 zStKLy)nf{z)mq0`sH)9jnIfH(5%4+*WU~y5tmvNM=%%(KOxMhJA;vVlLM{7?!6v&0 zKOLFV&i)$M=3hyB<2SQk&UI{O>FjD2DSj83%-Q`Vj_l2cElMxFQ*QT)%j=aUT4ceP z$_M0)tb8LGGn)KN2)g3o7f^L&LW8HP6Wwihq34?YOltYDV$QRC|4;6I#+P!mR;Y_0 zK_pFz{p1_}ZG*6(*I0Z4-D{`K^_Xz99Pu@rtS_m)kQ1sVyQZS}@An^5d zMAt1lBw{>AM-xCsTJ@)9SsDXTjZu1=X9Rmk6*la znrr0^$3W4G|8=IBRz+*LlnUjC`Ut0>1y((p&JRcP!+Ga4;-8duPpmiq%t@YZ+i0ul z1-3+q@c>jrA@yB}fXX!yoZ^E{^G5fpr4{xuV5td4lc<_E6R&LFRpj6AO9*dVRcQ)0 zeevSc!>}T~yGo{0?#>sORpHT8Dlg-;?bgHCE3Qqd-VeG1w$L%$(0x?SwD+mahBb>M zUSv*Gm>h)~y!!$ZcjuOZ(lo^xy_5gn1<5LMDZaHsL#raY{e%ewODHzBJo1$}n@+I& zyfvS+%^+yyL65y1NEs2^#(cfXaX+0jk3%Lp*S5rZy(Y$4-N0wE%iI{36y!0ozQ1m} znB6^C&lFLd@LKYJ2oWpPM;hu#d=%UlEaLrjDR&vL|Yu*c#Zq_mv^?>H6>1Kkv`^H*SHhdCqI-i zN#GwJ*M)P6cfG8=t4qvGXNPKo%C;>OI88;u`;dH0uWR?^8YA0%djRGuMZPShYHf5k|NC* zun{8NNC~5Rz-TraAL;Jg*l0$F!oX3ABDsxGQ__ObsFZ^G{NLyOdOn;F=eo{0_x(VCcU;o}GR5J*}*^8*h zRphFe`}s!mGaCk5qEe{;{vszjwDtMXail1Gi`$3KWXJpv3R3$Uf%b}$Y8V=J# z&Wo$HtcvOKWY7rSUGZluFLHXQo&yn~RN@qGtKL3-9BW&;iz znavc5cuDx@q2yo&9Tkc#Iwghx$nuZ2EDL|{t*0ouC4JT#{kM0mZo4w#TedZXMeF6% zS#fV->!EL?S$FV1o3QfZE(SXP5*?rm?+p3b3FqN9njr@QL8`>zc%+#n*Se@VV>w$|JOOtPIOse6KR z@|->LTZ;Ny=y-YG_)U&od)jVPJ0i`zKJJ&_ z)rV@jo+*p#HKg@bxDl%{h!rW+=}M59f??qtuGkAT2sKL>#K!uXurgNUSrnmAAvli- z$#6D%E^ju(+vevbggs(LPhMRwBnYUtp89Xrg;bND1nD7NS`Ouqxnw17qC2Nl6V&hL z{o_5G9vABBsRCk=>0XSdl;3X!NG=7a&hQ-d(=?G*n!~uCW}U?14VoH&XhGKYCR!RNDnQpgR%KS@3L0!w)fH-+rxY2L~eO|)cnzt zNZ#l6>oG3E9maZ$olkUGh*gl<$-Ir+V-JRRESY%=Tc=x^ul>B-SWd!3yj*%F&d;ie zR;N4L37Q*6jz@K;e^Tx{662r7TXo9>2sgbc-ZXm`E1ChvSdV;gfYKe z4ie?{DJ}#Rr_Vl!Y@~2#}fYv^1j4C(cHXEBwh+ zM(!m15Xsm0;;d@$-5fx#Qo>ue$_RX5pIcnmzVvy+qMC$U6wi+}OJ{zbEj*~vqO^vM zMug>u_z1;qVjb!~SbrneFn?$d#J24+NL(F_M!SR+`+R^d3 za0)eLCf?$xq{BzzBRO7S>0s4d|^K# zNWCCb@lvf0;fAxWLJ2(jYC=A)A{^f5$pwX^`0w4}LiJJM3$e{hKqx>$1N6WT7mqZ~ zS7!3B329_%c{fy~6wrI{P=A7sciXw@H1}>j@e=Aaa*{HgVg{!^ z77qL$jjjEdwF*qam&MxjLI2IDZr~Vo3`VZL{H1uAVeOCVI&mUPB z$vSegEYj~shQR&}&DL*5yF9Kv2OCfZ&g(D`qqNKEu6*g$LZHvWg~K^>yOBu%Z_>Z{ z{9s0|D*Qxq_$=7w(4S|EWcTS41lSI35Flt9C~0*<(VKH2twiWNlgXBRm-tlJo0IN} z*3L(HA#-n6gr-NVI760qKXaiu;5JYR%ff42vW5X6F-q;O-#YUHh!)vja1A5kPZ4e= z!}xd=lxMuV$?p3Br}@9PN$!*kaRMc(JD!7?GQ#6FKJa zJfKB1xc+s(oe3w zgjV<4U!NB-2whGoXTQph<=v}jJJ=Q^#g(I_>iGFD=_hm1GfOuwkTH~pTmSMT2p zR4~$mBcGQ>#!vO7Diun2;hmwYj~DX$M!yErUq2C)xQ|#))J?s~;lr{c%T5U^yn$Z; zVx(FQOO6c8r#PWb*HWKkrQBmt;;05wsMFV*JV=_t|l> zw9ePGAit;QdVC@sMEKh~^q3!J&7|++o3V96<>_{N#!|%nEBSL-%PO3UQj_ql3gi1$ z)rbJ2sQ=XP1%Us(iO_PK!g^5h4Y``+pgtgk8>0f7*WYgogE(#b+YYH!CW z{h8gKtD1~nzs_};xEXx!cS^~3?dC_+DxGaTPiOM?&uy%1A(InTg;!p-%$~d;D~v7w zpRPltxluL&X1jIH2%F!%CI|^>(g*zaed9V!&|`TSLtE zIXzd^Nn9bakG3LF-qL@jBVRAP4_?^o3P7q@jpb>V^sR`=dQ~}OAdE6Q zrVQnZb_A_zj~{fKeqnhROFnfyb79@N%QcnLwmYe-X}Hi;5AA)jq=e(J8!S^wH`mjU zK@+~F3tP09x$Q!s^dZJOE<~RB*arv7b=r@%*mmqYZTi0HL{{fVk;9pS{m+Z>5`l`EtGW_NMyb@A@YmHZF$`f!4Rhz(LQX~*rTN&PipV6D#D#e0Q8 zjZg5XT|4iuS|TtAEx1?cQ_jFfPF^uU(;V)N-Ef#i>%&{UViB?e-&$MmKKf zJY4PX*=vON4?@hzj5tl8JdU4NU>O8J5{ z2ITfUt=~BOytUC9erwy?WW>)E!B~i*h zVb@6sAbk7Dfj(hxk!i5sf{zK%YRsh>@TUUullz?jicvMnt*BEibm2hCF#YstAY@Qc z&TzK>m&Aj6Q&{`K>V*>S4oo##LWe2A96_&GzgHCG&<7ldYW3wW3I$N#0()t6VRG#s zrjuJTPE(#yY9<^ukrVdasE=0IIfbnE#`wj!ds2kUlbZY8nxM6R40aa&Z{Eg1_v~7r?=^8mvO&ddB$TudqUtr>bkjKxYJ_)cLy$~ zD&nW|dx(Y*PH8t6;BNEsY5`I`v;hfd7-89(sMJfbJC*uTzmoxm?T*B~P6SAamt=Rj z8!Tv$u|bD&h*5y-AAM?qH|AVxDb9@7`)?#~nOCLZ&kkK>wz8dq^Ow&e^DbJ#A0G)W zGkElxwcv9%wjGA)y3_MMRQvlmQp%~?sD=jDfX{j6C6@=F`-G<;7ylAv!_0~T>*n2?E+oai49EPw6V*qS6#u^7 z6}xP5>djATcW|>glb}x0!&lcM-Ul;+v}^PZ4=$dfM$P0Ek#pMfn^mN{MyjD=K?ipM zfitpOerLP#aoXd);WI|kLVJa)-SCVoBu-88M661$LG`6<**ODVT^QJ|Z>HKe-rlok z#{cQ&t*NrQ!ZDWAoLImk9acMh3NG@6VyJ`kVX8*Z_k|WI^vs)&fz!NYBB$p9Ljvaa z0d}rf%R8Xb4s)OUNWtlfc>Y1vZxU=d;jHSddn-UhbHwHfvW6O}v&GDeRW_^U44wZC zUfc_bN~f=qk~nE1drnE1y9gWU+M!d@XE$U-1*UbN#-#&QkV+|M1#r-GU5vfA>eETHb^v4jB|S2GM!R=zrJqpj0ob_ z`>(GlU(+iRdY*MAl655MoCIdZ(Yxw| zKL<45DbI>Xsp0qcs`N0d>QMVm)**LD7{#g(SD*j9VdY~{nrC*1chz!b67XIdzEG`c z(qOU4ky^yWXSB^vetski@67J_Gh}pg%yxKU7dZ!Z7QSP$#P2AmSHct4?|eVNfWAdE z9sV-xS&8Yf*H3`_MrFvx?R$Z!_i45QT%a;$SDLYTw?M&Y>!7l?Fy|&8D{B!;wjefM zQhb}Qv(&lVxm;C_@2L#YsujZz^y1TK!^;46)OQ}s2duN7DGeRzYhF(MbiI6VzHB*9 zDs|+v4>CbpoJl3SkdA>13JS_bMO_3vFigTDww-VeS#nlcqHPm-H0vA`9r(8d0K(ib z0`bT=Co;y7s^2=xNb3I(4>S3Ss!o$fwGOQcMGfAUnjV7ZczLTH{sDy3Fq~()YOqhp;?ay!QFnK~2pDO%nT z2!4I{?a5rz(aP}r57np*u9%d{uE^o0aB5WRTY^C9 z_@f#|rsVHEmo85VFmq7PVnu486o=46mM~k)zJqCoT7EzW9tVM-a*D2wzO zs!pJE`(2_(His779ac1Xf;p01(6-=}Iu`@Rez+ckT7-jmK1}0AF;c%F(hL=~*tIRJ z$qT-5@q#9HenJ;bu~9>w#*!sm&V(e(;8>Mhmzh5L|M%?mcF zymermFd3@aAvg)cycn7b>>`EP*BdP|q0Igpi}LrAZR&$H@}F+h0oHg?$oA(FpD_Bw zGch*3iL1LO8Vg&_m9e1Kw@)6e6gx_q;y92UAev{`QMGrp>hNh zCI3IUpo7YOu7FzVi^{27NGg5dz$+OcAuZL^@VxJ=aZ&$IU)E_PV67|oNDW!?2H(ip z;0pJ)6}(ZgGmPIV)$osfDfNBw*=aRdJ?Nk1o`{LEe^<3P(xY7{sbhU*NST@CY817u zfSgz!Tj#RO;SpT9B$Uuxz&qj$GyPplEy=_q&C&nW#T`=3K=S<=HRZ~jppAh1!OfG5 z;wKldvpWs*f9(}r`2#d>@ZF?(8^ww2dxJg*k@o>~x4}VUSx{fAN6iw)b-T1gzby7z zzz9sN0;Kd3_&{jp_?;qxwvC{`fyK49+F0-nyvZialmvg1_lvn9XrO$uTW&)Wx3X`( z0#ZN=HBpwA+$E+<5I8xgxFMd4sQww72cM zfa+3th=DJZ=b?oKSY?=~fBYgTTIHEt^3_xYDB&Wo@NtYsbp2?-?UDiIPSI^%Qo5Ah zbiJF?LKZB-O95j#byK4dQnlzMGl`a|@<*_4j}dsRrvf?dt|YR-}OK>$YVs1&S5svA*y$o)1VerwUncl>dnvc z7eUd{i<&rm84yD6mjzlsvO<52P%;yv99Q6y6>gp_#5~Oz6hBjL7tp&EtKE*5;RjRR zZIxvZ!&3;DDUZRSh3FbO0*|@>oW)6S^zp;T4Gjts~ybPvmjM zGySg1B4&}WM_U%gn=!IGPlzWTf6qHI!Ys5?R^IOo1@vw7Zj)GMr0GT1C--3I8s`38 zk#F*MExkNwgw}1oKJlT3oZnyi%0CLa#`PfZ9%@u9(IUs}PQ*Fx%b2 zn_66`it><*+?g%ptmqClE{QOyn-CU~4qpFqr^zh!LS`>jI19nI&Uqe6Vs+0e`M57c|;SgX*$mbvh>OGRBVe>deJvSOn472MP;I^d#3sW0{+GQ z)s!x5s69D~w00p;$$PBr(H-rW(c~fv^Hsf)Cqf62H5#MIzHPs{;x0deggSmkN)*)Y zUv*OVmB(TDV6hyV(L{%thoHsPj=kLr^CLZMhYJR;xm>D%R2my<%U!&;w$8clSq_1}rl@9xAE??$g?_ODaP6f?*brxMj$6x)A z260@1&lN*Hb6NaVeSF5-pdKlAI4W5G?SZ$Gp8TG6$Tt};K|8+bU}ugGq+@SA=S|Uy zXws$9*=T;b25O$Ip!Hn^Q3IK0De98_>8H{1Rjv~@h~!ZgXCIENC;aCI5+(SFhOYv6mNd{CjENq-^CVYD~%_*+AEVg=!-=HaB$ zA4v0BNYwkFsy8*Yj$S%DAcL3S=_~&Y=|M^q$uj7FG&><~CyV+pkKrtgZmtb3<(jy1vw%2T9+1w1%hR=lWg_BJ++R>)J?Rt}w zk@J)173CtKNa*7d+c1$4?G6IKi2e31SRp6eLPujs6kSuJ4(bcd%Au3{^7vp3xN zm6_JWa^6^{FEOwT9^KgSq)Lo5rs_{ z&@$cLh2#@p|tA2Q~Fi#)ZzUwi-5alhGPgX7%|;Dsj5|hJ8?PmuCacV#L!w zuhT9uyRf>p-N9E-O2}gzy8G1}#4)`4uHlH<*y70n2etsMYHxECkyTW(^ZoWf#+j7V%YYR!u@W`n?kWCQ+)NffhOQ z=UWBq>8!xw#=xgosFm-A{;#cohf`lA_u7P8!K`%%#}9g?6Y1-hA2mf36fbi3|4ln2 z|IFX+IAW?OlP}_kb63wB?0FNVM)qt~$Dto~kf`ioXE?C=7C&T9s~ChGr1aFt zbPACDZOe;&j_#-N1Na#5dVxK17;8%WT}JuB>nTo+cp5U>yvy15NJ*!vihGW#g#8;T zX##_E{!G|VGEAGavv=m>BhTMo12x+bc&W#kku#cIjwd-BCi9!W zZF3`gs$S`RAdNd}3bwhLx1;Wr#1Z4##jAAStIbRvx%Y@|prdYtTk$bKBTh9^*Zjd? zJ8%fiwAK(2WE1qIIVppQ=2K=|RyplwF|>qQyLa31bK9HoK5C|)6-xq28lCu;U3xqE z6%@uVi}BF7rVp!Xb=*Bz^S%8~Lgmv${tuuS5l20L3p;!p{P9A0!{;rVgPqIK(3}H} z>4c9DXR^UsD|n| za`#+)IN;0d^r=A z@bflq9;B>Osd8oaLZhxnq(Ip2U#Ht?OHMHU2%q10wbto4X+oj~4dJAsHa3P*KfEUm z!LUZ4Qs9iD>`@v{R+CT}Ad76*wX2Rg3~-bQ}|hsI7cR zzH7Iot4&F#1~Ea^ikt zXETxgGzJPxSSO!`)%!i<>(VP+rOa+7p{6OuVN;;Q);+r|N9{K|j=TRr$|l{lcE;ya zc_-YC+C@4O-Mifl+R~x=NgYqw4?l?&88!MqL+N)~(~l!{-dZ2ouzkP=HY;x{JwRf5 zdGHNRXm!+}pMeE?YG+O=FU;g{?=RHGN?@Q_mV{^rE7hKA@EO=Q4C?JPeWz`Kn*KF3 z+@d|u;r8_PJr^J(9OW6jaJJ=NaGXs99;R64?W;-Mr`dKv8E<`W*34gVONbr)kJH2I zKE})pH2#~peJ1>+asdK4^gqeCmkYZ-urFQ~*v5TwEcvM;Xd8Z<=HC3G+H25$!hc7D z6L9($p7w#mDN>o+Ex1VUZhG3vhboAMjWVY2yW99>^>V}Vd7{!;Oi^e4np3s_(W5A$ zC$^6BK)&$h2cfBm)cI=Mh+bD=)T!jvZR$Co_LR8|D~fNPcj<(;`BeKE=Iuo`eXo$d zQyo5%IEfG}NZ%fPe6p<6AkhBBZR4|yvbI&te+Md>BUiZgtD=9x!r(S+@xKe-{78qj28)JBl6SuFgG zq*!zAwk34P5Ouid3B*h*hu)Lt)d)3*8sCVeMk~Q1;}E5%HdI=7T;O!VSAoaN9>?u; z^L51S9+ne{d)I?+WvG~lDb~JluC$1MH8Iv+SlUIe46OphTVnXz4{%j6h?tS$@3S4o&blXQP^uDdzxO^bk6S3Cd-bYe@hI^o1-o#WjGDrFHL;WYI(Y_-;9O?ZFa~HJ z8xLbGz>y2&`Ql4=^4Y}~^u&hOUJ7AL(C~WXe5wcWeIcZs`)nnvu#}#TSLj+yn3eqk zyiup|aOpJhw(4pXBxY=Wss!eb-xlQrk71xbe-6^m1q~*R=47|`hQ~A7{A|M<9YDy5 z6h3$4@#;gsPLoIr%| zyp-isGcCi=%g^wLrHc5bMeJ^_t2|zkATz2s9zM$e2Hbg=rBT`cE%-F0@x)p3N+Yv6 zR5Ae35t!)U3J)|T%;S^<@(?npDCpApu!eZ5Lv=TT&c%Q8@$65IJ8GmqKSe)ys@w0i zVWv+U4%~zqP}!&Kq5($%stulqGGI3vl5p~GE71Pd`0ouLhalDzmdBNgCeHm)()Bxy zA=_na3kQeNj^N7o9P8cw$|UyltQxJE&O)(D$0Mr&(&bkHxe}*X#YEm<)i9q5_T5-8 z(|<$$(Aw+cvL|92Cxgxa3VrnLv>=QBI1Gde{rzXiE-sHVkREJL7iOue;zBGyGdqVZi^>pe6rgqIcZi(@9&4~C^Yi0cJbXh6NjOMW6(Z&ao>=A{82Tn`2pT9GGAIS&mFj3s zDak(kqtDH)jW_qYP|9-#tDmIN?EA_9#5jn0JCw1}ldb8duqrp7hiGQ$>Q~g%bEgf* zD<2aG?;}<=Rx|bL(j_d9^LX{DIUd@cK6*^ zo9g)T0B0LN6ED|2$*=ZNUgL(QZPK|L{w{pATWv_++nf*T+?#G1`yVATfO=i#bM@sL zcgOHfSx%ZIk~1Qng2V6Fp~fTa*Q8EcpYYrfb4u0{(r)g%in4vqZ#TGr1RL!<(P+2B zAY~*XRXTP(ti@0RzFL{}Y%y9X_h;3gmCkX8fPMTi3*63&acRs zMO1JgY$xtah0u=YGnt4Ph--0#|LO?Xy|qB5Gg@%ret?w;y_pa&KYRNc{=QN2GF3zQ z&A#z_+jCb_NR1leRCD)C1qt~>Ja7-7z+LXWc}rgsZ5-$^YgUa6+=BZ38Ge1CeB)fY z!vb}E0n~MHS35q_3ao$Xyq$ErpP$)69YbmO)tnGr=%OvmS zdqIY$KEvW~GXn+lL*eh2<1E)t?I6V!vyF%H__A<}&+OE_!X1N~zF?_2qqV7ivlYRV z(Gsvm&TSy>7&ymHnOVX$4P?Q+<#vC?UOJayTV zfLHB$vC+IP@sgL65COZnrX-B#lrre8_A6J6mxBpO`%*~JukDALk&FN6 zUWB%_E;(c5C!iB;QX0`c$V}W=zaO=M#D(b8p?-UeY+UAGxz~5UFQX~a3CjiE)c@Se zcKF@ZNbHf^`V8yH6Pk3lI)IQStAX-VUjyH~5QW>@i3njf5h#D6(C5#*9r0!Ul#iV3 zuXu(PUhTp6Tqw$+^qfZcEAQ6oh;9WfDYCWuLR)7p$_pc{Ga#GIysx)l_Lb(bGSoV# z!O;TIA}`~nBosm@E0cQ=#1l-9>IGP-J2)|P^e`~?!Ww_qisr$`Y8Szv7Dd|5DLN?) zK`9!4A(4gu(Ll~u#=d?<%$u1e5y?tn+g#E=G#?e^iS$G7MJ@bg^aU`cBgzVlr_h_% zQhzA7e$E4#en&1EXYf0ZcAP!lxPm`NgOGWWu3`v~KWpaXy9hy>pSH@C*IzR@wV9{L zdG~5}yn*Zb-dI|At3whq3-oh*^qr8oOkqL)0Cd$6|EMv)`35D0Ns$siV*e_*Oppi& zq3azltyp3s+8dad>H|g9EbbGImpxq#m;t^32Fg=!WQg~19f6;P#dbapY7r_07RGI; z$}0PRx_EJYtR3ywgQY;XG@zyxqJ$JRNo6W*#609TBkq34p8=u2jIN0yJvzD@TW?Ddgc!=-!ea~tJ zN?Y{W->%)&$}E?NW`LH$`>Xx+Zz?croQRu6joNsZzsG9s@lQ#xUw*-wpoSU0Lls#| zWXTq@S%64!qHqR9Hdt`Qww<##{y?H{{P{DQ@qY2}FZhElFV8^0fhL&erBs>g67AGz zh^!g+?^0j_D!X!sSwC~!h#*1@u184NvWK^^W$ExFU_5fGw-N1Mb<(e4e}41YFyDufFD=8 zO)~UEVScPpDznQLhm=}$gPL;elc+20exfXVit^&N(5%lij+nZ%^+MU1n@+QLL%X5l z%EIu?M5p*{u~M;vyVQtgYh78``N{f+Lf@_mBYEx8P+*cEwDZQP(7;_iBp$Vnbd@z% zh%Utvw(X8$&X$>pYfW<|U>I2UE%maBY(v~B_xUTh=Cz|QVp$d<)SB}m?xh(qxFoPG z6g>53A|$in=1YF%pys+fDD|?O`cJ0=Qg(WsuwOpZ@uS1nst&XF*N|8(m3sd``*Fh) zGvWm-Zd%Tw6}{EvhbzZD-f21^`HEn#)_ulPH>%KN*uGl&wKO@QBtBekhH0gPDWJ@HrUo~P9*LIPBy&W|z$n{L==8i>s zZtK~@Y7fk>PL1U*;tN-SmhNSgAsL`wm#(f%5ZdR_Wem%6Xe)7?PqrI~ahrAO%T|4GsU@r$k%HHqhGX^7-fybzxsCKd?Yz z9<`FCuLh+7p8k2EIoI*6O`zH_fsnSeSHj?HBm-7!ElSuA?4t8atMvcspnUp>&Hr)O z1eOC``oPx;#3R+G+VXh=oLV+A$Eq{&F0XIY{MZ{DIE_ZG@7{ksDv@7yQ1=D0SHmSq z>`46-UWE9hZv`~?Vfq<(`4C)VGStCtd)4GM-z!Poh5^6EjP51Pw8Ud9jPxTHcP{;^ zkNZ8YY+Fz3`i7J-WCvT7v`C8Di8HLAea7d}}k%jwcfc zy871fYn=}8MU z!7`K>HZ2g{DC4}OS9O@k;)E}t(**l(Pva`_b)*_xr1%fE&mvA&T?I{>S}^=z^ZGJr zVdZdqu4+VzngCo`0FX^zuxJ>6c=f6Vl*osopr z38Yca6k6wJ;HZxf$S6J3zeMk;4->e%;T`^Q?aO#4rH(dkxH+Fs4N5W_A?4u#iOY|g zS1u1p*+W-8pERCY4wbZ|2(OcRkzUm8{Yz+D2O1S$Rv#mzz(br9Xj4Y!Ur`1v}pZP9Gd*JuEW= z#Wzi{F?63*+u`3u7Vl@sj`i_K^KW*FpgLD=*gS67N&$^H3rsX6I}+YlKjD#= z1c?ZA5(i#B9eAcx4p;3C{-KbxSxXI>N99&%ya`wzsK>W`R;Z>W<`(WeG``vZ(vIJ7 zwY>{kzop2WyY=V{zd=|6Sef~Z($5B9o^;6XoeOiCZC!65W0eiI(VX(*r;YppPvg^{ z=8TU1r(t3~=#Ml4YWQ4oDMGgJw29Y;;Bhtl{M~Z4UpBk`^URB9YUP>ev!AwE8ub3I z2HTO=ns%o$M-6?EwXeM&t&$oEFeIk_K>a$(3kovo6m%JHr&#}g^2ihW8?o<;`x|69 zrC(|cX7;_6QobRBtp&R+ho|IK(#x^?<}S|2ZA(AtI~2-OwcW<=$r84{IV_(Aqtk4s zwdY$UjipeO1_lm(km_dbDJ|RK8jcG2hjd0tx>tth%>a9LfaxeHO3oSw)?V!1^ zYO%b>kE|x+%8geJ)Tb5X{L7X9Hr!g=1=3f!Ln6#wO-QADD)I$))QB2NY!)g)lUIT7 z{o}5x%6e;^#|mlla{_@rXUA|8V{YRJ@Avk_$Dq2A3}8+Prcgtw>SUlEnvK=n*OHWM zD#T9-Jpt#mB*L=J;%j_oZ$!VUfxWD87=AJ3mxnY0{c;-_4!Wo73$|~hrP{68bSa85 zh;0j|$ISy-5-aN4=oRDTs$O1cL3`Lu2gDgwD1kaSNfc=fIdO{HZfDyuH0<)B?el5^ zcztfHHb7m_6+^+tFWNHD#|MMmds4+U22aaM2B&f>ZR*Ml^-zX`hT|}3nYoU!1kCO) zfHRFu&E8V~?p*#eAmAK4D<{rkkmA%M@ziI^x%~sd;?dfQO|9PDu`yu0Xw%!B$(z1% z_eHb;Sx=)vfv@yqqub0eyW{{-of9J@sbc(+YnwIT0y7>`L|hd}``{(i7CW0Loi}fP zTu~1paDYTJ#2gU(gR=_z|6$JKMuMNcq_B#h!&}kVblP@KrG)FihHE59)g%X;Z1}Tn zgA-maaZ=g`4d31_zKgFVh;&`M987f&@#fhHyXDTJa#LZh3_rK1-CrqjGLK{H!+Mxf zYd{mZ4*WbuN8L?F^f^UBBbhz2>thK1`G4C68wf|GGV2ovCK&1bQhAU5UhHt zAtyviCtBt^TRwvdeCm9QHL1i>`c#s59oURJfb9;}jvnCX$+O6Uf(Y3oR|sJa()#BE3||@{X!q)JUGUU6ej}q$Y2X%2v>O8uChqI;;?# z#bPmt@+lz*Oi@rpd43bgPNKKe<=JTw{#Kk-Suu@V;|zX4tO|~@ObMB({|zzUL=<)U zrIwJc*HX(|luj0FpHX{TzSuGh(a9T+UlxG6@WBfM zdQN#2d~#-v0C(f^X4U+T-`$viGYy%3yJWhFCH0u-#`&ofjL8=(HJ(U0UX9U=4tr*d zq`~$r>Xqf?i2u*0=^iXHymOYRFN+Wz%PIM6^t>D)Ul0urKGzj#?JZ1ul_IUTB_6T&>_cYk541==&dGRGPIRYb>+Tx(VJ2>k6-v;W2Te>27utXNC)zx-i{pR0s%vW zM4Brt(WNTuOc3W6+*_p7blKjh5(B+4F(GZxsw|`P7?~Fp%WNx<%QRg{3hRF7ouFiY~y<~2+G-tZr;CC*VTwh@%gj|yv zL=E!b*=E@k3wo`$9xiSqjm(D@zI`Dq1qalcusrRz&8!_9z7 zHCQ?y!LDH-8Im%82kb7PtUWe^eSfx1dImMU1DKH_xLPe}NQC^=pWrr>e8UPUUW8op znI0pHe|4I3QdW~Z&`ruZx!wx6f9mJYuTXq>YkOp=$J5B-Y{jTwTP1$0Exz# zmy(P#3fj+uhU(r)%mF37{G!WO2}Lv@=e&=%+|_2l}SC0J&~EdYF=0^ z!bW)c#}+F>O@?cPzigW=_B%rh5#vdybexpK67Fxx+%j9bnIE#5?XB)>jc#n@K123gk&#h(tPCN$G267-jU_B@9#<^`w(i*!S+_~D-4yz=ra<{xbBT@iCSh~ z1t;dcWspWF%c{zn4~CbM*_D%6Rs4dzSvE8ZWg@)e&SpOGHj}j`QhyZHUeAgc#y=7+35sX+pCyBCjNlDyHiIJi?S?o^WY`qwkF1uKSgT*A1Ag@ol7;ev$x&f!v3C9O3 z(rFw;Dou+?}){Y z>46AJ4-AcX8k9R4N-V!x8Fqp4Nsu_%DY){hGf(~_LlGF5@Gm#2G;Vdo#8V+Z65-y# z5o8Ie*q(@hVNtsc@8R*xc3?w+kzt*8v{5N-ve+F%3eW88K3k0Xu)&u#AzKju!nU!y zM-}-_53Yn>`fdeUiq{Js(JJ}NL_L-aN8+7tV^}-yJf_%x^9y^q5G}OzS8t>7Qz3vc zQrkUmXfxp>`@Om9^NwEJN+%2=jeg#+q2l^3vJCGA95DcqFs^J-eLx{xry;^9llqCy zk3?#w0ve9)W$rlc4)^`k$|VkJmdpq=(^pREq_=@v<-@k0Svh$!1LZ78G*z@{U(A>c zIJZ0XlBWA?dORg{S;XrFzBTt7-Kp5kG2%gkz?70fndSWF0%>|lRq9O z$E|0r^Bt}5zB3sK=}DHCSxI}b^a7Hl_Ull=1>?3wlFQuN+i{k^0B}UY$+5C|%q@3*H12-fKQj@KV&7dzU)b;!(O98#On?)n7TpVQl zmG!lm&)1*i?){CX7wzVJF~yxm_YSW0CPyBDg{u+1JkiKQC4< zI=sdsMBz5TWrG?{&8QsFB)J|i)uHgG{k&FnnV3Y*uuK8o(ro^8x-_140U`NF3(EOf zdrPcL`?teQ+3>#ImA4}9?$T)VXtUlLSB`RbRVVr*9+4OCEA`hO-;B0L81~kACnB0h zwl6g`CRM#U(+zOdgk*lCmj(DIa4h(J7c$Ox7TEnRg12>B9`?obti{8we5s^Ju9LT% z#VPr4pT$RPlD0ALK3R!>gS$)9T?J58KaTwFQk!+>A}mHusADtyKU|yNw7F|2P>|e$ z*QJ7Q0}j?x64$(HM_;;RquzB-bha&h-bb>Ry(G|hs=feS`j*lGx5Np4@xJ|OK*b5o zmN!F>51u7=zq8&sSA>+j6C;0WRn23^jb8s|&j|W$MSt)fLfAj>>HW*u$w^nGwloU) zr%Oyd#P+z;8zJ+}OZbb8^S)I{{hW>eGlMDYa;KfVc{`%5bc%x6N_D-EVH8fiiRK$? z-R*-~Zq}pbE+5dhg6hc^W`ElV)PC}D))hW=K0NPGhxqA2`B3jru#UJyTbB+5L~2Hr zaGM52{=W7#r8_-N^TkP-)u!*7D-mJyc;ZX!?2Y*=^yXK#_=_oR?;zq#DNe93 z6E&Y&l!9)L z?U?0v2*~P3_JgOoME8TVsrWPcM%^pWLV{AvjI{{U+MQ-zfi9P3^H*}Fym26O@a68W z261hxl$h&}SL}N%UAC+h)NkC3EHOmH|Ni?)+q+&bYcf={o;V#y^_8M?A<4jKu>RGx zKK;~@CMQbak7kVqfOZZLE9naduT~zsjp`2L{PjgrdN+9WXZBe(Kc#)rTfIZVq8dHe zHllVOe>9yaSKPDY90*vFvD0=x51Ot1)InXITYl_bBO%g+LUU3&ZSyKWTzs*Pt+2?# zO_;Fc?m134%9(-PaaegF@5se6Z8i%Ym+C~^xTQ!NiHsd>?JpdBpJRKc4H{al9g(!<6&ywubY zs}kmT@;H5XB``O{L?82cI`cbTzcaR4=WQC_V)nqCB1$3i?VP+FGaTf8vf@xl&prqm zC+u(z_IdVJv|wr6E*0rJgfh*kQTVebzk8YSs`T ztQ~Q{QS+Wmv=H_|mRmz@-B_pGv|rw6Xl z2z|`@kxBlDqJ5$hsCJ4mgkWf-M60lNrgHTr`g%F60cDz*+&Y{7h#z~hRfs6az}4v` z8I*#1a9N%nscI0GCn~K|y-#X7VwvMr#Bw4ZhV`)js>OZa zM2QUKu`@+h!_cvT!loxW$U6sUdV^Vr_Voq+Omy`FB<9y2gPEX;$hHFM8)zPYers@p zF$CtHEOX?rl62b1K9~5Try@huW>cnW^Eyx!wwYn$RWpmD>>(bi_ytYfq!mjXe#+1d z!YE;RufFLqchu%H0$+XIdCrxoXX>mX6PcY#L0i)ADq?Kc7~^6td*;bSQS(%10ZL{p z^UOWoL2>FIe~(;8@eO0v7ER4&TQBQf)JtC#vq(zGag$rh^H`5YMr{`2ovO!7W?w#=}pUri-vrv?btX&#P9*5vwt zyoNVO%^!aFyaZ6O>?$#uSRjw1PlC)e`!(z?nfFKheF+I|RS==k1R_;~=l0~kACN|2 z)n2EX%R0B~6Vz60pvsu}mOMk!&Kh;&Oa|km-}X6wS76cf*mJh*E8SZb#TZceQK#)n(4vZ!L;lLBXER9_(7e&N(e-d6V3@E_JfoHs+C_)8y7i8Qy^kY?D#UA4=7J!f7 z-G=mvEa_w^ZfnkE_Cpt_Nr;;uby$G{>fsi7?)n*J$vIg0ij)wkOClRUc1RU<%*8P# zd5!Cbjmn!w3$&-=hWo9$b^d;BV`umVHTlGe(q%mGvWJE#iL&H3^?D@8O~XH+t#zZi|?Wji%oW6GIblM|;3_`?Qq3UadDShK;-_asUCGSIog1F!}4C-|O9LMi7FfZWUS z2*e|DNP5Df1KE(T^)-&MROF|CY6|D#V`0o~Z``&4$#X#ACZJ1rA)lp6$43;sH1}K* zO4lvIaho1UosTcW>!Mj(fwDeQy&&LX!0B*TKB>&@ow{9A#hiorsrQf8mh-pqTYQ^} zCne;q9AwgXBh`NSke#XP>?_fP?#Q81 zr7Me){(S?`mAzue$szsqTW0l)_{T0F4L3-GZ@6F|aSYQmMlxKJF;=6;WfuU1$* zxI4~qUx#+7%1pd|zdev(LCn)MCVb$nqL$YfX-i~~yywk>7xp_edR6Qi2CwciJd;r+ zk;b5M5%R(dT70$MshvtglT@)|Eu#D71BBFB|zHLTd}{y;UP(^dCJn5537oK@3gnw~AvP2Q<|4iu$>jXPLQA{VX zf}1rcq(R2-wiT~3KzI6woAoF){%zG7X_|5&nai(_&@OwYaKpuZZMmv`)JIc3nV0Lz z^@FJ@Nax(O3bj{Rwo}i28onjqWv$+tEbIBzrS*IufcSj`IcZg7LvjU^22*y^o*nq~ zbzZ0#gn!Yv3IT>ABVca^BMKoDGg(aR%g?6M-zC%>tQ0`L?%_ukRRIMJ=S z{LzvF%v9BUkm}gdB!3)OxhdJed0kmWb=*4en}_d*Q*rYJ4kT=DD!=X}$?sT-)|mei zJ@$_Q@(CA+>~Xk)1DA|9Fha#`0zRbK>?`ldzXyfEW__tN6T9kQXFM}}i@y7IGEt+eYx}J`dWydAPXCBnR*8AgYb^)7h%v?aRdPq&})x1oh zQAm@IObgm_yNVngYgRnr{F}dZ6I~K+|5m9?EpELk$7vJUXjLsY;@Tam94;0%{g~s% zfF-uq>ShhX`WiQ_Vmbzj6EY&t0H}nFca}D6k`zl28)*e~a#r}o*~9YRRvM=Ub0N8? z_?JzUX0VNGGzM}@ybXWVgSQ$h?f+ZQa?q-y{p2nRTIv-0xk>jzz7jmeV_ zp@|q?;q1d9G`csku%7U@+FbX!zV0F|y1hrxf7a&F(aSD@1!@k7$TZ2mkC~DjXzHDT z8SPn`F|9>3_!|p+$n}cyp0F{W8muP`ln<@_kiFdh{PlA=_pmIDf~lrTOkFX`$(SJU zo-gMZ9@|y%7sy5GOD(U2D32N=C+RMXP3Kk?Rqd9eN_)~L6?a$6U(VonUfH~f6F@J&6F(qDbPYf!nl0vmn<$hAewZ652_ruuk!d`JW<=CqF@sn)Ck2oQ{2_w zI-q2q6+pvlWK=bpI#0!i_(^Yzm*Y68_CwX-QBa7esRFt z{0rcB@|#5@I-y9QX2*;-wDo=44^Ysb5b~pA{j4Fl^3q7=Nl=an-6)NxNPLrKcVPAC zZNc?T+12ovn*~N|86H4YBY)=dyS=p!+uLLgMCnalG<0WXgXDnq>-yczwK6VCDGCh- zHGsNk+?>Ic2gs9#0@Iu@yuh`bT-x)Hy}BOD!>;mz4^btCY0CVj2A5UE^{r+9b99R? zxW*&he~Kos>pQRfo(2BOjfBzCZ3G_r?zRWK13!eBUTVeUc&FQkJ!Ilw;aOfaG)V<^ zU-JhIfa|37gJUCfFGZ23M~z48(~a&Jv)d%~^!|YM#MTDI83o_h#;jg5$i^&&FvCi_dskE?u7WoG0{uU1W#=9E z`^Du|%!1vE3f!NDggmUpekSV8ZIx;_XUg{~>3sBXfBp`51R)>Bq2^zk9MKi*$cFrYQCX^B)96tqTe$ z>kL9$Nwt}JPkh7=*|Z@P$qRSic2Q8Twrc!?X}Z)d_(Jbl#d1GNBwVcyy=c7FkLH=d z+_~BgBednITWCNIj9S1I5bIuEagHZ|F7hqONCOIUndi=37pq-`vz4)*VbA(D|EXm( zLAE(Tu!z5#l{7--N5A>5<37hlL(%@D`3C-#KAxjK4eXxUNE95jzBej5THBn+TI?Lr*mi82D~Uihun70D zX{el|m;1g-$Sfr(7376XPA-XfhK*{wt<9*UHT+|7_`a%h3(n0n)+?Gq%0d337yr9O zXuPF5FA=uV8lgOWBWnPdvStSHaxR`#a(d2u7#64gG<*~@n`S5tbYxN%cf8jW>svPY z!$gmJ>}1Ii60Lo8wLpYDjirFLu=+15=0mT|bhW|h-#$~WyoN^z$*qzCxjHcC;^fm# zUqUS`zT^5;!r{YmI3)!y$-Fz$l zGP)}DL#qB7ZfjxbF9;T`EjY&;Ziy|6qXdg{?8l%d;RLpNHKdy+hCMD)2w}JfuAZ(P zGX}^dd+=|-A=3!4^*2Q-_$R(;{DS)&QVQ^hCxEHb54t4ATsH>-K0n`KFm%}Aa9(`& zs7uSgL_$a04vyET4bDCt$l)I&M`)WnxYtPTC>&oD+9cF#f?n*O{ zvIJ$()jDs@zWEMyuxj6GLH*T`!hfx%TS1I`nVfxPiDnZ*SUWYlfbac6SL}`IMg0TY zN+eljpA>5!C5Wt_xGhvW3tFaW+V8P0Xz@fBF_kfIP!3~TJZz`+{3+cda#gt0u1_KA zTA^U!KeV2vjbpuX!V{-h^t}qjm${(fSsRAX(~;HgRGr$OTY9$hwSjy~u3TW^YL0LI zjTX8#(`_$vL;Tg{&>HY8W(U=G{llJ1pCWQDaa^eJUG}|)ZC_Wot}thh9u5@*b0Gip*q8UN`lzoK zo2{AIul5Wte08f6;J&A8+4+gkw3Co=x$?tA@ppAQ7u5vjHvlR(S-s+xoP?zR!8h4i_im!E9*-dMjL(t}H_S<5zW*8%h^EYL!hrA(vbuPW*Nie@c ze6u8rVR|a^oC6~C#AM6;l9)e!BgaqjB;cz`3fP^88euZ-#&Y3mCi~1KfQ1}U`VT3b zDs!BYLATqH+@Y|0>#Uvf?GG(1?XwT^kcMY1YQQTtaE0umR0-@P3t^7Z{q0k}jDDz| zBvcxau?HkjYyh7IHXUXX&XhQ##GnH~VV_W~6I#)xDlyD)Dka zk#u;GmZq1AHcyRK4jf|AV;5~Ue=}6gt#UtjYeED+)=fc3&0Z$sf%%}FA@)$GA#IIb zT6*_CmX%Rsv3Y}1PtlmZYBZp$Zew#(7~)vvu$>Dx!NkqGQIin| zVaip@aX70C>&4>+2*NC~EHbiA_fzl@pQd@9cE6_)HJ!NfRsy)*!r*_E%U;-2{K*@fwCHZmPx#|VN^FNDLV z<3Gd}4`0N&2J|}-m+1V;V-4MN77h8F%`F@}~bW*{Jjd1L~TCCdUYTRR2~&8xx@1 zaDQyq_m~uaD5NCs$?mY>6+*SnzJ|HS&0QF+!ohQ~aAheFD4ITf&UmWhreD#*n7LpU z^n#!Ms2hLuA}OHD_fDcl}z-!G(_L!l=Rk??P|tFYfb)P{ErFYwy=8RPR?@pO`?H&B6(AHdNqqK zN6U^PE>W8qj`{W2A5WV9v|y#kv7dkK;;9z#mWZ(q-3iqnHV%xF^tjQxR{CVn;QiU6ke~WVld&oDcwTDNygU^pxOkw>#Yq{-@I-%5^iovwJu={> z>OTiJMq_C(W5q(U`CpF84ME>JFN(P$Dh#Z5+h1;2ydTh+7Cpxw-g79(w9+n1{w-!f zU*$DZ$757QNVM6*fa+QBRyZc%es@7dP+hqBM(d%NT+`6&o02l+^GUf8rG0YRPp-gh z*&`)g7hKpY^Qt~cmJ)eN(~Vz`5okPR`lIAB>swI@FS5&z!pr~11W)FJ-bFbcKP&1n za?qE}Y8|#zeTq|)pJ`F)vR>hn!J3Bq9R*p7Af!QVJN;MbG0uArL%MF@dqSZiQz z)?MLVKB{3l)gNlO6nU3|gQ^mshbZ`AU;b9o1T^%CX;xaHvtWCoU!rN2lz9}c@Uhse zaIJ(QhQfaEsoI&nNN{=11DeXdFJ%Rk4)NuP63v+} zL86qPdLl{1Htw{|!&Z=Ld)B>$u!2dqBR3~lLG33SX*spr0X`4yK;gqd|sZYUUkieM5@#gho@v3CDH7^70|fLrSHhKjr~ zVG}?i4Za8IyjKj~fV)A%93eej481Qm5^gmF%amHGvOEOmbCQ=DZ(cV2Cj7-_XL#xb z=T`s!Pxte+|K7bS>vaBK*Z7KS^~sn$0X>VhP9?R=VO>gh07)|n_H*E#Z<%@u3hR88 zTPb(JVXkVj@YL}N4*PEs;r0iT2$h9@@4*$P3)_2|yy)e{=G3cypklq|yK?-* z^N;eq7Gucz_x&8X!JDQ}<&TnL(T~y3X=i^sZUhX=NPl**7E_nwj9mL!e0Fni!}8x= zG|Zo6YXx_Ag^&0|Q#*?`r6&>0qHz0NvipC8yKH*Lq@X~pB5~N1g7a+YJR!&-OCzUR zMEfN}-0!A@1FzDR(Ak)yxLZh%!`)PE;yrR47~)XX`N=Y@;B=#=+g0WGXdhL%!EMrq zG!ti} zl!Jgv?EaxwucciaV?$9v!(Qf=C!Q|ah8}DR)CdkN#XmfY9%t{Khq8!e%v$3pQDu}k zwI8rDnQXzMzze0w`u)FwkdUd@3%b9kyVcOf^2UQLQyu45mY&#sZsq@%U=!w6UpxrU z(&3|t|6x93(*hbb$o?gtUL^D3HTs8#u4#Nmjy*M!J_8?cP;3Fs0$bYoWUlpkET zF;OhZF@LR~c(hinlLahw*tM$1x?h8@UAs53>3r(*D2Jmn7OGwJ`ry~4Nz5#;{c{KV z{F(iShk&s~Nrnd2)9+24FX!L&P$O8GRf2>w#k)6~BM5McBWj9*fOBv74Nr*6o@n;0 zV#PPL(}0bS7XCX4vM?doGr=XOV^jW%GTuVD!a<2&bwZE5p7^^4$?2%zEeyB`t<+d@Yr{#US zw9x|dtD@o-KSjIrpg0~nqSY>mQi!)fPU6rp_Jsl4Z`Jv** zHP+gNmYHd%{qh8l07XE$ze3Pu?@Rt|R!FIoZqzS)>LIZir->o89Z4bhS6{fXE26e} zz~t55jPCBgjO*;ARJ-P_B6{5kR-u)pw#dx{CiXG5NXL7ZvMD9DzUO2Z8-MNm@tf*; z52<8U73^Iw7hb4&YE=M7tB+vG_b*)^vRi7y_K8Q^KcqMB+|mzEdYrhIw7J57AL#5- z@~XG-f$zC(j$aAYX_Y&jX9=xGl9E;1Z5b;ZzGY$_3buJwboy2{WA6MQw;;YZhXHC4 zSu;`w6KysxE4e5~w?B)X$wwsVC^iu*g4@68gW+);5qVet#{}z8iF$&rN=JDHyb&5! zMGY0kOa+IwkCHrd80abTfvwl+#P?Bs>S5#%JJaT*Dt4rteKbLXwhE3{)%WYE7Skwd zo6rbpe`hEDC-ytr;eVH=A*V;rljxQ?kU+PE-Kaq2G8W>M=Kpoe&w3JiUuR0GB0F97 zH=|K2K{iq$X}cHjB+$st0WfX&Yv)ZEIQ8}i_`K1~)o;Vywfk$Y5#y`)Tli?__Uw1; z7FPXeY7_F3^pT6Y^pPa_4ql8#o{Ap~i8vUQ$79|Zuqoi`<*S`Q8JV<}0K)u~ByDlY z35zY4pNy2g*Y^x@k8JX-9ZC5n;f*h!IHVPE_E^&Xu0so03wOsgWZVZ<$d#Wo(0)D$ z|KxXH?YozpI)Zg2lS~wA| zm;|%i2EXSGqU0hG>e$=6S)TZATN=FnK$|jMdf#F}_LioV_x8iwis^*)0ktl)%i8O6 zX$V|J5Ehkro!p|RE378)_ywi42s5Cqm91FxFa?3LsiC-&$--$I5cWj&05`91GyH#B ztcJ##Lv=2Zp)I+v_eCmV-y&syP$k`$-8A1;PI-MXV6Z#x`#sBp2~1BQ+PVCV;~uRS z)4K0GbJT_y>^_iEYbAQ{q%(~|m^H-8i^VW=RrifHc9D*^*Bu-(a<58}PC5G(SK1IT zf}?MRjQY#99Vl2jr*>SZyVEvuBBQ9zJct?Jpg1GBefmY(LK#zy>n9u_w!$gZL*%y}) zs^-tTbTHKhGS*v-h8mX_)p}LS992lm0f9>BAQE2i5?H+<_8J@_uil#rW)1dS)7s7W zsPA9eI$$WbA#OU}*nD`6nwZqdp30p1avpsRb`CjN>ORkFdWv0sy#c6J-= z-5K+NSd|ys>~7wQYPa&yY7y`gq?SzQnFDl&oFC@42btaQ5Pgn7w!zi1r#@B|4Q|fP z`N+D}{+l9MK{A6>*ZH1zVl=J>Y<1nJAVb!vVReczw@ZgaZIbePq9BYHT#7D(x2xJ=~A}y!>O|b(o8K^Q7U$U6~MW4eqtOZ zL-uqmZs0=xWh~k@`J<&avN&h0O7RR`>*w1xQ%5&iGSYq-Kc%UVKF60l{loGk)vt0; zio7Y8?55v9buFV2aHn|;frduQmQr#gU|{Y$V}8z`F{(zw6okk16-?($Hg7!7 z4)q)xT5gU(C6-DH@3<*de!RDvXd_^mkcV8vunQT_fq~tHx9+%aF=fBIohG6v8ELUR zw(8XB_A zYJKE+S=F=ryV{D4^+(EIwuLg-=$TeFE|vL>|sSOdex8WD*s_=b8UzrAn2;? zs$Tv&1js5k$>DumY2f~SLXA6WK(a4!M<@(4ujW=|6Vkh>x8k|{HTXz!Kc-@-d4D-~ z1^qe|AsrO_XqWyAKm``@Q_I|fCj6iKS>gQ?6N&$knq5SD_$Q8xtS@DpN5|V*xnR0ep&kj(fOHKGDi_abn-}aD3M&9q6X*j!{aAmr9 zV>aYh8rorr|6C~2daz0LZ_B6Iq+>#uo;NSli8=PhW$<6EoM-uKxlZ`uk=lxsNx}j; z&=h9FbK!AWStBU!aT%7)=;f+W(M1)kxFnU4e@nfaUBJlP!_GVoM~8`GO3~ns!o7O) zlP@`G#^&+#2Uv{`j)%$+1Hbat12);;O3RVS_xLYi<(;T8Kv^w;mw6ak5yDJVE0|Re z2N9fqSbp{Dcki8z#Nv}j94b|(v%wKJ`*E@gau*UzQ}M$)6Eoi7F-nPj8h!?p4?On8!z|t{StgKD24@W zIqmtzp3A)bp$+fE;E{77Rt;gdB$S+|rnq+RO(YZ$1BXJbf0#zron!%l@}Wj7=;JYh zLAc!5yC~I@$Z2SsRWX}xMdU60$NLkuDA}J=7}qMBT4GRa8$)GqXj2t%b1nqay6Duq za39H=3+pH&ef7)t_0O9_3iBCjF2#_5oppc7Hkqjd?%$z*sicKN;*`v_u| znTp(8=Laqvg+5Y`cDre|(2?M|1QSpLC}ao_(P;X{;c69eI?6>&A76#mf68*{nt$t! zife+V7kp}AhrP{~oPU8vd{u@pORP#9FTC~eF`o20*OiOTl?7vx=`~lnHUo9Rl|7&Gg7uo@8&9L5DEz?zQvB9!ZiT{E9Y`BmZM}9~ zDnd5ki&f2VI8S}>tF<*M@+I2gpZbYAgC#i7ZDyTN-^qxG^$C*@){|7_Shn7oCVYj= z?y+yu*hlNY-~L1`^DC$jAuC^%_UD;CqLU23cv$VC-7zuLQp_bj?`C{--p$CBEz}Zn zGwYiF=uXxY)onA>O0fCsoK2$4^Y^)T2qQbxCS{+HOwz_dg(pwuRZ zv6+6~+LjM5LAAn-LD;0Vwv1g(rtvo|ZrQ>(GgkG7ymibU()jI!9X=7X+?PkRe1*d| zefH?>hg#Ofk5!)X`)BBck7_;vP1bG9p)1y1xR(&NX#y5E=#@AHh}&ysdmeG9@_A}S zU7l0BqQ4T$M)O>Q6A^w$Bx6}cu(vhpuc3Xss5vk$EY^FW?aK$Fc*Q&~Gzj^U7$p^>52bi~h z%Y|~z_AS%s5yip z8x>^r9Bcv(UaQ*7ohGSa+E~?t{@kI|AE6dOz#hFOal2fb?u~}N|7c{baYAV#+V%)E zk+sl6rO?&bc@WZN9-5XP zfK(eY)8yv3Gpcus$`>w5sGsChpa60AO>`^}VYhT==)3wch%Q@Z2CSI3kLelzKt-Rq#@F2lT1@9u;XvCLA zt1lQZ0Hk_>ysxMre*jQ~;^$56T=EHBs3^wfl=M?{j^VQwK;OuJ}9(YG%9ZX^)UHEqE4PB#&H?&@?!^RHU=8 zI()w7nX|}PQ}dX9_?GLIpuGFJvjth&bjM1q0B@>Ty=7&(EF@m{KPJmR-aX)@V@DD1 zAfQ96gsS|Cj!CR%Z8W4-3bLBw=ry`fIkqHbb_7=p@yqFqJd!RY zv7jB()w9l*pPif1`|#xl)X)n~#-MU(W-^~HKn#(1S#Xhod1hU*|F1@C{-_S z35)nGDq$anZAurvuiLm{9`Wc<)4GH5J)2FFsJEcHEO(>x<4EMW5T{g;{Mp||hXW|K z3OeAbw=W#_yG$b>rrn*?`><^;U?;>PElI4QhhBkxv z7Iz5~rYHz4m1M*!WB+t&HHJ-dAzGp=*)=hXBSo*dD^Z*lITB{_+&Cl7GFpL8^tt2i zxIIYM`~EdTb4f}35%T8*{q@%H@-0Av&(qnG2x z7`Og(Lya^4Uea{B*`xT3I1_{!x%N8^DWbA_dli>@OH)fc|r#daajmkT)TJLhcf?d(?0>3Y16ndpC~z+>|5>f+F$ z?rC+kUIQwC2yckQ+5R>{qmeMOEZ}^Dagy#9*MR0CJx(63l2Jo6+@n3wOnQ}b*gPY- z&k>@Ez%zvr{jGa{7_PQ6CP4*zmkWRO=**T5YH#sUWG>)nnc17jdCk{Q{>71jm#=(m zqD}vWY~D-IZjChEy|ge{6ULgt%-bAmvFAL~6zr;|L4Q! z70gR^R$aa!+5eHq;e_%_dZ6F~miN_QJpNDK-yCcB0Z%l(Shqcr_^8i4xnI-oqTMT# zBR7S8r>&QWp`;L4Lvn6(!+3Ny7t-#}ZR>dYS@~N@v244+W#Y%@_$rg(R(tZWJ1zXS z6dRmC{bxo}PQ^U(!m7BZe>|urpC2DKp6y-A?Gi0!6~(D@iFg_x5~-xb^`qg8?cN+J zyMVB49iS^pS9$qH;8}(?x=~^^wal< zAAUne`xk!wkIBuI82c%*D?L}hzEJzv_`iW?6^7{w?hpG---$@%(CoA^!3yNw7a=8R zyUh=?GI7#%M561Nq`X1FWHA1*A5=D5bF1~!ovwX+OCxYD#2z@EL> zIRq=3YKsp90@2OWf2x*fUJ?_g^SUrE%(U~xie^BmZsRsb%$7MQl`2aaR(hTK z;3oX^8P_>tIMntY`ta%;ye#mv7g6mwJUI4q?&N5I+huy<~+Cs0RG9t>D{m6t`Obdcjc z{H~(!D^u;IpHK{Hk&$uUb-da8!!@$a&uU1=8m5$Q!$dl<*ap5{WyiuX6Uwxxf1-UI ztH4LNpS#tjGVO%Ri{ClIW79b>fUVi94sVc6UnP(5_%fc7k0jrH_i~l}7vJ66 z^ij^@C(yn5b@qO#nDzo;>WrIGHJ9;cPWSseznilz4KEsk`c(gfm`b`4Qt>CdrF~_R zj~%`M{SPLk1s4||=mfdLoFzz+yDIwKOjT|{Sg=mB3IJ{@#dLW@^f*Vv#(Wy8 z+Tha|)H65Kme`Q;wI0VGa6a$euTyJSeC;jY`$mmuq_5GP8Q1}PyjK8sMixE$*zoO( z$zcyCdW6Z|vphq%3caI#saAyLbA~B-8{ETURmDlKnR0`On1SE^76S6P1TD%K?n+?Q znntviH166n?Y@8dZOD(=cj=iQ!RB(0v{ik;E>grS@NxRqzzf%A-Nh?}f|5A=wK-Km zJCYlR-;=NlJfn#IIFpD1Hb3B3%=8`3DI|cd?&-*WAHsF&b7dV8m0ZhH>VY=zAUAcpRQz<<1 zzW$wI-psE)_JD|x-oavR26lW;{U=rX=;=lAcJ@cC%SC{)@5z_-gqzOP8hW{Y5tN}8 zRu%9<@m+t-Xza?YFP10=i=VwN-Z~e24U=HS-+kpNu0j zNLU~x74BWDz-GUII%_+JSIVvDzTaJVuT)pgCK}L=D9CCP?9%sHOJGlOUr7qdFPKJv z;Lg7Tf7=GUZZC;MZ~I-c;1;JZz0Rwd+VKDG;{*=LzAi~8+Y)=0=^GMn_S97>Qp1=S zjyIeYhvR!_BcIKMBQglfia zlSU8T%f6w7loWr!S6aTkr&PGT2Jlcgg90{l5>BbEAeN;N$1{O2K9uv0U7G7&rLW~bk1#$cv*OQjUJ;Y$eXlq)(s5Xmm{GVL zN{!o-`U?>asEyjZ8_c680JYcsN9@B6Ah8soj!Za$K;?af;(siyc=XI!)gPjc$~EWS znJ&jLKs6%dhSSVbi|yxr*<9Oc#1}n!C@4!fIYj;B!V&!@e{ew;^si*xmvRo9gQ0(L zXRr>Ky}Fr^DQl$5Wzyxi(YqnAI8l3(nme~rqifdW%0#R19H~7XRBJBrqTIxRx9Ek( z<$2ddyw>m`y9Jqu=j7!;wZ-4EfO;%5S|6_f{;63|R|M zi2`?mRx9aG`dg7NcH-P`w3RUnmk(MXUgsFr~veof3z%M%g}&ySf&IJS`sX3!s)fs`)6BjsEbx>SeeM8B(! za?q!TG*et3#SU%m2sK=@kz_7mzACOZn8i=xex-n5m}^<-6qIVbuDa5S6&IM16edPs zF0=CES-JSM5#UKiIWt#v?*WRyL9aFQ>e$#oK6+%s$c+kA)MR&e83YUC@Dz^lwvWKdzaR>CDo?7*dvL`>r zrKf*xLAAxBvfDmea^CGtr1Zs14BQl9>Akf$?i~v;0nN~^392!T3KO1KQg?A z9PV74x&xOu2=Dc+6zrPX))n3LzAh4z9h#iy#?JBTF|d?AiXu%aX;iyYUy)0PE_4ws zj^9luJQWgv6FsLhIcFU}p;>u5@t|@Ec61!aUC> zpbFmuCQzJ(i&mkxJOYbcX*W3XF80K83v&YOg{-4UuMzJ&{UQz50f>{3ZT85Y1b5@8 z8|20PR%ClSACOos!KP2S_Sz%5&lp_fd2d!$ph%FbmT<`@FQV9kmSeFZrtvc#a1^7y z@AAoM{>~%E)k|Lf4dlFI1t^KOlL&R5zgE>)*~6ye_)IaPDk0drUy^WMDHGz1Q=8j! zbtNdAw0B3gyOJ*w%f1`9oR#L*L1=@&bZMLcU3UTQL6Ec2z=i?Jzt4-Snel+tyK64N z(|7ms9ucN-j!OX^#%rZUX-WJ|;|7NF5s-XX4X5*~Hn9R5j=}DtUN@jq|BFr0mcINr*-7Y7l-iQp?W9~-% zode=IZS>j)!*%JCL&K&Fn_VwuyAxG||G?q#eXxr3%ec*5ZuQVSI`uzqi`(gn31P@X zj8vj8zv}3E@d^6Q3#8WybQG%b2n-t>C0KH>mmm_r6d0z1Mj9l zgyC+pYG5xg>V+K1pue-DX2kL`Wac-9`s?U1P6I|-3n&qfiua5SP=n$S8oeA++ve-} zKuYmI0vJR?>O)8IIc5u%@TiDHE0wO9|NHj3pr&jqM?u}Ugn~8T9IN(;A;hj3YK9EJ zY4|9niX==_G(qQV%4CHd=**N_${oi(NgNWXLYl~GHQR$^kx1W@1JU7UB*@t@O1EYr znLUEqT@;L{AQ3G>`T{jxGJkmnh4;!%Bchxp*@a|N)xDKoA2z_CYAN5Ks@JUFt-6B> zC}RbC{XVL_qKa?6=(tlo&CjpE?YCfN>T<;|;;sGb`;esb-g-;@>_~SlCqk{4(_`V* z1n*-HoyW=e%OcJ)1g$r1eIO30sOw0I`qZ1QYvVeKBxG>Icz2P0q z!KdlAb$LqFJnhPs2&{St&vF}2m0qe1=#KZ0NI8_On0HqZ)@=;Xh`v_4Sr;R_=tnfn2UlXh> zc0kfj__|zIuuKQ1h7e->h1zgAr!QLSje(F{ph*m_Y&lHDZ|uv!alv6FDcH?5!5yh* zJsS_K&S<>}po5MgA72OSj(q`1*4>I!pjoT{Fyvsf+Ygwz7VTd0=I?euyg`ElXX%vw zQ!XB^P{WAtfJgrFeDt2Yv0hes5rSIKlzvK4$Bw^tbBdP!pd~up$*xh`3ai=dyS%CT zZ>rf>O%WSSEbI+^(%DK#fOKNbAMmrnaDRHvDG+;)ud@a=dWK%0TK7@&2x=u~b9Dy7 zCniOcYfm51r68xnAX>aLwJFE<lsTcd+i$J?;>DJ(XeUoN zjnnx7@+l^XnzNS2Sw{3w0ZNY#Q-%U_g-sk0HiqZP9V zY-mOW_12`S_kMoYK$oppngT-x;S1BpJle8(h-+<`86r9Bsy>!eS6bOLJUp4AoRwI$ zK6CRAYe}Tdck_h0*P`T*LD}4Yu>5CH|I+8KT^Vw@S)~^HWHV!QA=ummbW_@|P&(c* zh`2GMYe=Y-^LRJY`3QC51&kXCcFnsO?9x;=9zU$}#7)m3x)QoR3Om;fk)XfjbT>-+ zG9ZhL=C!R`1pK1p~mF7eeB8{0^P@*|_sC;5-7d03q;FH z49gur=XRte-JGLKH@+iei4zF{<}|9IxVn(KK6aVDg4C&&G6CNwq+7qb$;jx{m+!9| zDpWLrUy1L`z)V#&Y!VyeQjt>ml#&5TO50k>RGGw`@xJgXT*yUR{eF%MX6;t@6mKKT z^5}7=r;nRwR7W0SUC_*=U;WV<}!R~3gY~@ev4fT7GP;&Inm?HSjgt@nN^xM zd_g8KW-Z&himp#0k$JiycFrQ>yMaQqOLgWc0jKJHZW#m7?#0z@ihOpH`Zx9_OV`~^ zPvRJPKoYO)n}qsanhpHHZjn~&JYbPWa??`$o5Q-?X;iQ4>iblzb2lp1Q5=3-r&oGH z@%Y{R*U;w6VBrEr{t3e#G8N4R+=o?*f{lO>q5CXmC_Wpiib*fAUI>Jrl;W0lJohS( zr`xI6A^Fj@;zUVb&{JwSchFlQ9=Z1F&+g6QsGvkB(q$@QL!J1lY{;#LsL`D_T^Nte zn9u&xi5=u9{`+Gpu75(C&+Q;0FBqq$WeXCgw$HfGs}+*2el+fDUYQSztoGl}&y~-+ zr_pl(5_*0d+2DwM^iPZv7NTZu3Qz@;@$4ARUSh=;@JwDu7^F^-uVLn>x3_+W60Pif zzE7zRoR6~3d)bwhRA7C6Sp!_f=R&78ebpU*#($IQB6f>bYOU3=LCXAB>LE+Co*cQ`&#TLL}T8 zISjCN=Tu;4LI!U{0oAgOK4ht1JgqN$1ZvvyL~$JivM??H0boe&u;}u`KD4EbqG`d6 zkZnyb!x>3-t?UOu4Y27AiQBjD&j%-af%s3-mlMmlY#;HvV({nPV_HX7OY-P zDN+;Exz`Js;7ux=33mUlKc8W%aDm_ArW5>uM1sCX``N=WLNjc%l^9j8Rom|Z;ppCR zOFwJ_nP`}Q5c2y0miaOIgM&0_*qgfZB`0w;T6{r^^cC?=sGO`#D+Aw%vLr~#2 zNUK-Fe+@?=f8sp1i1gUY-mo6m^bpVG75Shn6( zQ*CIA2();m?-m%C>+U__0M<)bM9zs{b1uE_z8lYBsTEwCT(2gXH!JMv^c~DNR}=$3 z@PcXiA|LFyeFop?@`2c79hKa1-{w^@bNj1aq1?cLA`-K7H3{%TU6iuCbp zU_7JpdT;xE>U>CswrOJT8kT(m+}-U_PV9K*r#-5Y8*b|Ikd7oO=Jw#fF4SAWvVtEj zg@tAYP>1|O)+Po^jStK*uFgO+qP{H%jUVf$w5VNlTB;^dZm|8Z4w z`hmyhFBhC;;Iud_zmuGY#fnCzBz1y6+eauQSszG?ir{s zKfc^bI2_NXEj+)EWXK~lHi=;dY&kpvd2F*%Zuk#d_tk^jk=w@zRq-K!C-rP0s}C)M zCe(9JaUy$yFp@O^&7$G;&=97~g=8-iyO7#xYu#O5;CiEnM-@Ga^F4evD7fnFmvwvE zTzl=L&tl;~PjD^^>!GvdF3nBI6Uj> z@ByKt_3{-HEW|f}_-anncILS-u~J7Kb?2m6&kqh4@FCD!Aa6xphN(8bdDzKVs;1E& zJpABWe!9{}>#Q@bKQ5S0zsqNFq0LwA&VzoG-Lx)kNd#M(mKB}Ab)*@8^WEP!@&)g= zf!WL7&yglCEg09FyqtGdQCX*fq-9il^$je(MW?)5rS89kTmd4mGZ5|ghlfEh*hPeqrog&8@g`5P^*@T^zG2J;UYAeB z-=G+x)IOSr>tmM^z~eMu2L2t#QZqmR5$4xf?@8Z^z$`-n`_(2Oqa=tE{c6`q`Ei*x z8D12DM6FKLyOPLqFI-VMhkd+Zk^b_yE0L8siVikq(#4cdX(thnu3xlmIikM1}p>Od`xFD^6g;&art7NfTE-l-&)1N1*DJKC|&E8c&y8HcS*uLkj=q;^$~+z!6P+6F&NH$bHsSE72$Ji}rd}1Nl(@d;h`nk7jzQ8gZPM zF~D0jS?q-gZSI*!4l+$Uh^lk;wH}=34m=&&*M;A%`F@|dMyQ->2wRl^1_RC!C`Cf! zA8xv>rVj~ouy$Sv zi{kTrV}W^L9gQK_3E3%|bGW*7@4?8QqI1>wuG~31=tj8Yr-|i>+J;x^cAaRATXRWl z1zfnpk3hy`n@_*5T!iXMboUuR^}EWMS(>)Iy6t%#NmD$W>Yn3m?hq@p|3tmpNhoD5 z?e32D#Gy5}eg5;V|DCB=Vcw&Tjp^{2+d!kAsw7{(yyF@WGGGXLQlfA?YTy(i*uuB| z;WP5bS=p7?p4XJZVI6Tf`;jKiL*%Pc)60*z^o%?L6ywaP4>moy8$6zck%{^rN z;p0sKn|~^PjK@6~YodOvC>i7&^%kn0*)Lfwm^6n-&YNeH5^o0GYx|iFZqADbRQ+sf z4GtUT0YHLMQmVUFlltX4r6Fei!@hP+ZG}cHqJ;w`S;PBRx}U`~S{G{rW_*=adRvmN zrvPxh;Eodi_5m`Dqww8+4UU6MRu7N82@t!zrtPy=QiRAl{*WbcP^KUjT*uqN)!Bxvt5J@U8p$qF?;Q{lkqH=L(47j%&+aB@T4wERCWrtHl1e zk+s$1aWO6Cgvpfa;Od~i70@eZZQ6piIbstTj9cCfZ$#7io_Xa_D@Tw~mCRr9XgBx# zc>&l+BM)@%@tLgxZS1#d#HBig+~Jsa(lnkNJ#{pkyS`R%e!t`fLxj0mK@vmqQ;HZj zna&!SX7|GEXUJc%Bl2KAw@pgos7{_|ZcC97JpFw{-q9M^ZmR^Uj9L2?)y$j^T}=n) zNio$5St-W_(AtJV{|iJ@Fur2R{LtTGC?FxxAn)&9GT4KY3U^o>7onXI2}rwTE%gWi!MQCczN`G#7*L8CxF)Ad z*pTmo!7jd_IdArAqmhR)N8$DXO;K!DxsuD);}R)PtEnHW8=pPS@_B%sSE00?s8mQ} z?@DGQL%Z?pWOlh=IfkiUKTLDDVDl5HyLNR-o6d{oe0q<$Fcqs|JnhyV@f9Kx+nTlB zcJl9C(5x^Cvm_qVR^Hy`&Yv>IxC?zZb;{>ZmaAMGq(^dhuSD=lx@sXaWj2)}{vC;G z+LXWgl{@Hy#Gz&9bmmmr_e@xiQRni#vok3(ott=zz|3LoIvBo_BDZUZY;-(XR|12& z!a_ueN0ShpkQZtP_m@j6Z4^56De-j*v-4q7<`~pGv?0B}Lq+;%)HXr?5UJsj3?GUz zKZtDJW4d%E39S+KqA_vqw=dI7ETiVB&Ffrj!|b)E=cS8G*EAAfLI$iS3q zbs$8Stb)XB|LiY0_ca_jF9mw(G;D6BrxFr9myFqz|hJ$WN4}T;)N8RKa z_~G5FycpZ=x$~$E=B(^*{f^q!F3H8PWn6mrKTKZik{v|5=v12o7{aM$Sa;$m8AD!y3Hyyy2((}SjLK&U#P ziJ1PGJH1q)J8_tCG(H;$Ck3CKNNWVWn_d1eOpPIPM~aS%MUkftMJ$DKID zpq6mWya}lkE@rdDC!i6q<|ozW+SS|Nhs3m;n-+);!|Q1|klWNB*`16cOLyAaUd746 zDyJ<9I=m_v=A-*0dU`$KDd5cJCtmihfM?AyTDYzq;1y~a)Ruu|QPfv_!?wnc0_Mwz zkM}CJ8((u-a7>*l=KU2zuYH0v`u$kJW`w%{U-yN#EoF}oLnfFH zTGoms26dmAn2EIY;bG)L-K5-B(lFI0Pk&W=d3|HKBg_nEI#mQ5%2Z?)JNec7B2xlG z!ePKsXf5Vd6(Dh|_f5AwGuRsUCf<>7C#4F|82ECSbSt^iq8Fj435#6 z5)!0FVKp9%#%Pm?<>S5TxXY0#^OZ~X5Ag^HP>;+^QKzM^tEs!O&|ehmC7T@3x{BxK zMs00RBw5NLspOj&cT@~l_tb)qM|oqvxplA0F20Q5d8q+&J|nTqlN)=-PDq5x``W$M zWRyO!WzH4F^FZT%p<|Znkr=_eQ6kVmc74Mw|7aI?sdhLVbg4VVOlWk!S_{wB&FQJ5 zqS;-`{aob)dHNaL*U<^LyITYf+bE8{mgqsbwl<6QNmiqcE28{I_iYiOtisK8UN?_7 zQ)B<(w7Ft6F4{+I-mWiVcLaG!wtbV3K@)LJx;ypW6RZcDT7N~s7p9^5W7DWfAZ>a} z&fN6{%GW>EHxdYYQir*4NNc)E*G)u>QEQBYLCCauj4@t(d#=su+Sxo+t$I@F%2~sl z@4;5aM+)R#UUe13ByS11U`+X{vhMi_TKoUbI1QRTPV1pZYQEj^oJ(a)Rw;vlbw8(V z!Ojd^U8x@r&>8t}7v0zM#_8wMbt(9IN7E?7{FPqgekWAlUu{v`qhr?X;$_tW@s_x5 zm(fUug|}sQYC9$9!vufJ99L4FyNHd{Inla5Bdc!yjbYB%-X~ZNG|h%_Z)&RDggQ~i z%E0bAUpeJa@8-DbvGAKqwUTyes4naA_*=V0?5bhOn>Xt@&zMEJoHh}S zJ8_%>sL?}?Y~bMW+7i+7m>QfbHOaGox+6F)imeRU|M}VOzMd0%HClNXSESS_vC&do?Xw}rL+^1vb)Y*j&V+T zq6F^pkDG{(TKAZlb$)zqz_@^mWRH?0Pgu0Vx2&MIdKgxsx-aR`CxoaY0<8FkJB$pKeHTY3i|CM|2|&t}6eN7m)l ziK6dYyL`s3ebK1UlzGUI3pSMXmB`%B<0I}T<^)1bOfjud+~LN@q8_#EtjzazbM~Nh zLsuj^+1q0DZ|P&ozCEfIfPAMeREra`3??P3-T9~*b0~TjIDYbCBPBMxv$A69i@(xj z1*?+f;9(*8{&bwad1Kn_{GYYUqbas0US~*QEsxKmwQ8N67A!>_R7A&sDTKz)>}IeR zf00)yHASME1dT=>?#lq5YXnP(N&ksLk9F720M}WmF7hh474qy*|BXv7p-Q8N7}TT+ zi27&WyMtg?7`YGSbD#Hp)TloY?82$YZKgm&8t)-dP`%9Ym77|#H4@8X-3!d?N?AeKxDScG~vUQiRj3HsIg|O)EJIsU} z(E!xA=zio{wS%jOeg3jNlks3lNN@#N2f0T@;Sjh;=|{&iMsAw#u-s=({&(gckM+@6PI))X{7*=g9Y;p@ieWMy%jrjLQ*jx`v?g>7+OXod z&r)*Ez4@A60?5O*tM(OL5q)5+b(Y-Qf=Ru5uj^V8W`oy_!rc5aX-+EmL~Z@l`7-d8 zlE$8nla806aBf7v@td!^;3p!uKyfg|tAee6bcZ2)!G99~20;e3=B{O``;iwc3dsFezj4bMx^ zfayk%9ZNW{uiD!!5ALk_H5(Lcboi84=-}h*eV?%qQn!sGShEdh$HaItDgDJ*(KTAKQ5j3WEFq0 z)V~ZZ>JDO{RHfLxc53z_2iuu}`F{36XgDc1gR*NyGE>e^scY-FUMP2xkfE_Qzl5D`a#)X-n zkSd8)+sa2+r&4cHm%Xj zcwwN9TC`b2I@ljWcG{`#;;Zm~EkUHI=~Q+%X6)!n`g)AFk0%ZbQgdB5t{PSbakj1LQw*Bu6f|&lK7xc!@?Tc%8jNr7^wFGdZxO;6}^0dd@ zC_dW|J;=ygGy2hp>3FQ$Y4gKxW_>;%@R3tWzDF;}kO&@)lAHiVK)S!U&){GOU}C|) zi5%x&5kg+axK_@(z5;gCa8Wg6BQsefR)F-=nR6fv8zwirz0^4RizZ?r!v{zm-71aj z=yhvZ4!3*Rkmk>k^Mxi?OEa((Exjw+s!h!9>8xyw7ij(S4Vji3bTkEG_eE5US-~MS zK#fL3Dh6#CxXOIcv)0KjGZaRcPVyDIwfa>Q&-bYm;&2b~yuF9_N>}}1$tpYdQKahG z(Nlpay$7s~a)ev2Pn^9jqnBMSDi)VadEzqt7+$rsH-pL7KluiA)AZ|lL)lTwU=XWT1NW2qKQLyjw0Hj+8HB-FeeuWs3J8rp;!-#E9o zzPF{2n&)oyNuo&e_?}PzFy%Ut&{IAMG}!PV-UB-eW<{5i8ksAo_EY&FJuMTf+nT2Z zgovBK{E(4j-vi`X)LP;wN;$`1S>f%60cEtwd+{x9-bUMHBKBQmDQBbzh$`Eio(mtoC6N-=?lU95w+TlHFn5xxROe2i-h)W3~CFBFte zf7z(qXjsS$(j9Z#1{aXbg2FC&$2$VlBc0R}Mms~?xujy_wL;yl+&J$YaHqU~cr{JU z2wJ5*tUD5XYs2`huYDs0Z*=`W=*Q{;Q@mU1(xMadbR~Up{2ewNQ6_|h@VU=E8~wSt z0F@1Pk_G(d_KCgbVXF*cs+a5)_(Df;plgve7em1?b;zqP@^*| z7VY;Q0b5ePxIH3KZk&3F-vH*ET~NObQisXuo_&UIvae#Rev2lX3;h!=4$nE0-{t=A z8w?M3=SDj9Svj%xc#;Ia9_!q7p6!-Q(zYC`{owbE>s`Dpj{702=Y+SFE7ua`VI0b3Xb|5o_i0XTwR1_>Owf!`>t; zV7j5BC9v0sLeEs|MUJlhGBE)Wou}~kbp{FStQbkq<0O)oLIA6OCA()EH8)rK>4VZp zxy>fgfKieWRRO%CLVqHC!|N&f}yKr>LfMuz<5GaH(F9P5A}g`?_j(#t@fV zpI=iDt@*$5us55ySW^)?XvFj-4?OQ=0Ti<-gx&mBS$=HrTFL(hfG4INI=vsK^}~ zc9S~}5Xu6_I7~<(IIb;N%yovS2?#3~(mcXSw4?+RXX|=|WMB)ETZex>%YPZ_%hYN- z$42T91*||;R1F(X6W-<=nu`@8m<9w9zfh1eKuaUmZcytEwZ!99ksJRfHFmDhPy7OZ zmCLT454iXvZ(!KKzgJX-u6wWU&p;bfMIvo+w$O$8u;HeB`uE2%3#SU0>Vu3U2iosY z>xxOBfM0I0&~=)x#wys^Qe_f26U;N(M?gAJ%RLt`BhElQXIvi#cCW4NG#Eut>BRIR zrQGz=g5LNyTnpB*rFgHQ&7s`yQV4ZAg)Q&u@_06T7m(^T-z@y>WSU1J<2n?6Ya~Sc zd)&LwwpJ5qW|{s>UaxC6U-j<167M$iimJsc*T#SV?MUqu z$5XbPHysyObcFqSMkaT>L5c%|BhewKN(Tj?3BH^m|^}cCmU&Sz{wJS9Y&TA^C_TTl1yWx>5P9^Z;WQex}d z3DCM=+{D=;V!d}Hv@(@#$MeoEWfpF%Wm;2uHvSFRg zf2>*hNTGlSj?*~%8t8Z-V{%5RuAXl;`rmHpo=9d_#Dt3pL`EIy-$PfArE zyT)|$Ie-)ofVJt(rT4Soz~A)ZB%`i0Cc~6&+Lo#N7npbf$L%dLWZo}nTuR( zR4-YEg+TvxhD7qUE=~ub(rS(fSh(v6*A6$l^v$8;A!h8SUglqhMUQ|`=#|gOD^Sh3ag#T(kXx6iN~u4bp~K1`>q%rxQkxr~B0{!w5Z{cTamn>3jC z8mBwArG=XG{oD2{^yWJr`+qhadx8-Cir0Qyo%kx* zhI(2=Cxx`E+CGvgJ4-K!mX|byaiFqR77y~m!O7Q)7=QjuV71nii#veUO`mWP7{B=c zLZ=Vr*suZnx>SdRWaW3}ZoJe$-bF-<`nlCS9X;W$8!^x{&wgZ!rFI8quKD*`Ig{i5 zy#rTMu#&#%^tKkw*UGfFvW_We#k|f9!8OT}mM|gyjb07wKCPG58cFB94U@iqt>sfQrm#~MDZ|;%5|CY_JE&dhn04&%1I(Y#=qdj z_KY}|VE+j<+WeKQp_rz)Hl!WNdZ&HpRoq=hhxYKB!VeZg7mtEIhicT0PnB43ew9{E z3i1y2g9oKPD!G-LEjoA-78vH=QWAV_2(k2Y*0?2(sQCof5%jB|p8k(Z&v&J;Y0XJ( zjaudkqL@s5`I6I*QeuRUwqadB>!>ycWmUrB7Zldt*vLd}L|XFd4{uM7C1y2OtqHdl znvKsW%*YT!!zCB(ixb!CAy+g$N~4Q`bMR*5)_M7t#go7QtjN3`dZyVwp5x_dkK6^7 zr|6<&r~q4{`t^{4akssYpg-Y7z`P;Ps9quKs&B@X>Pj)!3Moow6E8L7E5Vl54_0iAB&OxorrC zMPBZ}6I=vxd1n5{FRu$<6B&0-2{m7JrWOl>Q7;4917<8nBU6z)u9cr3&cgkCtpfYu z$N=r4ZpA%|H{I-aR4(GYF9KT67;5dns(LOO`9c@Sk@u_Tq6fe1w-gPZ_$kW>3}CIV z$A*=b#k;P0G>G5=E!2H2Q|5e~1LwVDPSvC*q*TqGj$@RQqMq`2;#-%GSd@Hkm3@mS zS#l+N3W6JahR$?H7xaQtErqUe-pS~Xl+05_$s}%Rh1W}+?Gof~>7D<Xc zWRYjJ;ko?$&aIoG>6mcD@nzB>y8C|M*u6aT0s+~h7>2qJC-ITpd0luyAb^vNPO1xO z79?MowetF=_P44xBY=D7yY*J)`L+LyP#E_oc^f0Q`mm<6NX$&qLC%zjL)Wj{+6og!FISL{!*%r!Ob=)M-@XEOBGg2UjJ?p?#Mq&sVI!v|acemN{3?G0<4&-zt+@>TcYUI{)) zbc6=Mt?UGTvkVh)pr&VQX-h?>&SWupGA1u$;iRxIE zm4DHn<&a<vbDWl3+rA*f^AdwD@ViI1)h&mc=S`cD^ed%Yht5ShW`CoOMCSgaSsrCs zV7S&S*+l(|kDVkm9&IR^1Onu%rrSYF#Z{B}p2sKhRZkmd6p-lAHQA|e>W77`k^bDF zV$Mqxp+Ln6AVqOADDm!5;f|1ORL!OOyOgK2+q8H#btI3GYE6GzttUWCRvZwDfo`Yz ze2r#mg7Tuw6PsGqH-$a~|8Rb1tr@99MH_$x9uRpJqnPi>N^<$(dTxPPBq+wxv((0} zcY23^V$qg)y4I3J$05%sr%vs5zLarL|DI*9_Utq)w{e_zD2k5j8tSByTG!k+*}@B{c*nMHCB%JwNE!x!sSdQBZWRfzOd(69BX0 zta#+(CZ^t&H0ld_f&xw1mmNN^r#%m~c~31fYOxu2E@fv`GCyiHtaf%nam91f$R{TU zpDk^f!+vDs7!O>s*WoGs_CDW}jwm;k!4q3n-*KSL7S^CGylE4DV)`AD5vd)Di)EtP z;z2k1;mMRk84zo2AIu?1LgSJq-X6E4u)x>PSKA@Y&qXpbx^76q?X#HvM^-AQl%B|C+eF|4_96?r)Ju zDYXoj8vRX;6x6+d`G&KuSY7=TjQe1Fv^`mA6@&<>saBch5}qpbyJBcQ?RpXH6=bzl z5=4MK2zIWvbRFP2N2}|%7o8Froo;w=z&kQ?T0*yd63H} zKrwn@CVB>_<#=iaxWk5CJiWdwbEAxtCzDh>&}9ozR6Ri!IfCzQ+?VaGhL9Ll@*w{A zUcSth(o$Nrybzr`oYSD>;qNjxsv0d-Ta@2#FF^Cdgdo+lSGm#@{Skc!z#ceQ&s(5$ z10`>tVl?*iFFPz%f}^(m`f=tzF!Ot`>y$&> zPq*_0Acu|4@CN~0^g_Zb4?hP&qrd|@!Jz)U&au^?Lj}v5xQ9B8P<>zJBWm7lWp($G zgttpm0lH3Is^>_`kE%7F=!K0I3GKl1JPiSo$1z=xZm<=`v`1c_oQ&I#C&f&+e8o?1 z%d~}MXL4R~BvF|0%;o4WKp)-(FOwDMvx<|G-yvYOl$b_=`j~`E4O8FRW89`2Wqt&^ z{a73qcCzySW zvAV4+9y?`Tbpojr%j@~a89flyV9`NkNJA08ncrsrw*@mk3^-Co%NGky+zXEN<#TVm zc=#%KxkNWTi9EeK_aocltppVK*)oVjkyYD3eR);4*tZ)Q5ZgZ19=Yo)1LDS=i3HB| z8T3C1I91N03BI|<+sK_wHoChb#UHSE)9=6wP#)@J7Ox&sA1;l2;vizV2(QSr_=B$E zwkm*TzaS*47#8{!C|v~D=zgkPN$$5z9y>}%S`o5{?9RTMV7}g)lyc+_82smcWiQX} zlGG&^$xoSIbSJ*r?tLsfQV2?MCZ;AIV=<#Cm9XJbx#+3>L)n)^%{6bOdf(z?LI*<` zxd4$dj5-W1mmDP)6xaB;;ctZ&UTk1UlhPO7Erq@RHoWI_;1wrw%0WOXTtO*0KnAhW$k8@tF@#*AmhBl z9uC$?Oa8JCNeudjVn~ggeYpD&o^SfcXqu8?K6T2;4l>w`O{nff7gW{Fk{YiqOyun8 z#UK@i4}1~Twa)Od$EGF|(0Oc2&8=7OJ5?3+YUA*SkK?L{;gHjB2uX(Hkpvuwk1?Eu zaUipj;o`gJIaK$PXv)ZXS)XnHIFr-RkWc@#Qo2HPzrel!Mh&|Qt!2U*U@J5kLLK2q z%%{kJ3*X8Mq-j-%wzh|nN*cg?&XVdT=^T;JHeQ`dcOQ|(<+QI58Lg(2735|1Nc$bl zUyXaCS7_tN_nmwUpy*loE1#c43AUHIrj)^3>E4PX$$-W90qdb43#cKRHedML&9Y!(GTzSlfVNy#(SgoNtuSk=u`_6r> z+;6sSX4q?cWnLDDajf!TF25v|FMqSFTV*m|;1Gar{Bo}p{5!)^=rL1zym-p*dDJs6 z^wdIR9DYwrgG6!*z4*eujB;LRzQ3J2FefZBM$MHn`=XUs_u7$fZI}&wEJS06w)v#P zFop2O6IA3>t$%=}$fEvt#wekGL{&SsJgw?b`_e^4bhhZ%52IzS*6T&Fc0u2yH>+6- zcmtA9L8sw9BeY(4R!oG%V=}*Be86LI#0GSi`sU7UxoyqxU`bTF9f9mJ6x4Q77?v7@d&j$>=cxht52d%-3`jx0v1G=kd zJp6y}E(e+c?A6=^Mwcx|0kNl*=18_ZxK1bXqZ2Drlx6W8DsL56?!$UuOq=f_?^=omG}E-{8P9^K0BSg4N!DQ z;kBysB&eDLp%O4t)G-jc>gGC#UL2wuQPW(zUN4v*VkT<1&wt35@id?%s(Dvs)HYt^ z#?Pgm^MHcvmZ~LhnJ82tGjcYpXWVw0xL78QWtSOu+uq&b48F^7d}vYT6J`%*%yieO zX3B1oNAZqBEFG`%y`20XwG(D^vxWv?J!`Zvz>OMJJq5#R++J5gXijcR+`Dt}PiR(^ z6g}>wfRVabi1up@4=m9O`?UnJLS`C7;bN`9jl~KWYR<4^FNd01$x)V%N5El9SE$FQ z&L<^Bw=mEQG|THK+^yhuu#;+FBP-wcp^7`3JJEi^AdpAj&y3nU6`c#0JuDZRD`jA- zL4p6`K>FarTOsC}mmLp=$K%NR^Ly0+zhy;)I!!crIo^uv2#c@;XVsXc#ZD!Q@W{jLT8XuUMOx>f^elq5o4XOz?!qHwi==Z?t@CJ> z!Kc}HURZc6&pCzw^7LEz9DEjWQy&~t*;xx!#$>8uZ#p(!p~v>bRARP0hF%^OJD(YV ziSh!e^pp&y!iPT5MWGD$&HW~J?#tkN^~!|_(2?X$ zhWlD2BHaH(lSArg;$Hh&!@f54xS``|D06xKvvDrn8BMieLfyOoV>#G1>(PF^`<%JJ z*%&Ff+P%v#cJsrVzouWJPYU;4_U*}aYlSwz-bUjFcg1Z& z`H^_2C30y#lWbTy5|zgZ@jRy@Uu-Ck$>vf0yuj=7E6KDwj5Y*Q1^G1ALfh_kbs>$pYJz}M5>4bA8Q%j|=?sn&U zZ%R=Vrw_Xc8RCAob789#pw%?r<;&Oh@c0guzz!hA79U20C0@Aq4$}wCWcds*sVjEN zJL-+^F~~AY;|<643vXlc2FChdalig*LE?Gz+} zd+{UZs#270ZP@7MS73$q#ZgMB(aL=bInC@IPQwwSOV1K*z2~!zwenU(b6%bLmG`{5 z`vpl^T;x|A|Kn9CKgo4OEub{AFs)J(B9-C3V{7?sI9Y?uNqu0yS&(5#K-4tLqY$|d z`>0YpjRYDnN_LE?DAvur3gvntbJ>CBEVnqC`m0W)*7wramKv`47tnYCPo*#hlZ;mrT;j&t{4qKmTm_rNVZ&=w=J7zTM zmGi@$ms5p0>N6jh-UqG7kH!av`E_;*FAjcS-yH1B+;O3pc6nZ37eAWvmz^X!r^-iW zMbC=Cj0u5lkZC7I#@Dw%S!4afPSUi=LIassn@7gF^7vS@P4cfPCi2{5C7fO~sR+C2 zChk7B{c}WfwFZjrcs==G^_$<%CSSxTUX#kp6Ez-Ji(&^yaq&-WUf2Mk`ngcEV2fGQ zIZu4CgeUDXomb1rV*TnD_J}PiM&og2i0-|HmO9UncB$dXC;K@YrMRDaG-;?#hfStp z_Mr$%<&18Cxkjde`70uA|Yz_t{JCozH?5{ay(1wyZr-q+}eI+!%t?rR2ih;y-0~ zH@mLuY6Ciw=#vvyO>my6a_It|?s>$kt2F#ghYh>Tn{UmW3k(d5t4YOAf2XlPg{)-(KQ>ICZ z`&y%VF^ zUFZ)9kB*8U&hPY8W+GY4*}<~Dkj?|7mG{~GgAOuxJ(FeKQxI4s>?eBj6m|V`I@Jzl zG~qoUZL=h`^P?3|=<-=_o;g*%c4_8$nS68yPBTa)y>G#jDsD`l5ZcBar^H`611hWE zdrAvBmLg^W9bBg8Ag>L5eeL{T&Ubf$D-#;erhqOx;<8pC&j>GP>GWy3wYFr7EG}m^ z9;i-5uL;~;Uy$ep&f0`m1QdJbL zQ>P3OpR(MuG>xH0zahIW>1LeFVxB+xY9W4|<}hZ_h>$L1?dT}KPwp@hk%|7kG@++a zD9QynST259;RmlFAitHSk1buNDtE50wAkvJkTD*&AZm4&&gxHMZGKq=ojTqFV&t+- zL9(bSS(%MI{LN8Wc(F4MuMzD1-RqZ1?(%A&jHQ?@S3T7Z=Oxs_S#Ku0l@<{7Mqu=Y z_cJ45N&_?Azl8` zEA80eD@rEtt*RL_;~;lTJ^xLq6r|@7alpnYz;*r^E>1q8vvY%zq;21 z0xU52yNVchd--d1xI#8ABScPXS|TAe>@y+tV~KtpzVxkks!C>Hr0F=N=1NqiG{$CP zMWyi5?@u2`CU@F)=>KRDQsD?5aqX!HPkNr^XG<^t7hyIQ^ZO1HMU4b+0axDHyGQA# z%ld)e^itOpVq)6DyZnxnTM-P?ipheBY@?pV23y^__gzVlo8am;KB{%8EmaT2+uuFI z_ZZ!%$1yEBk_2(J=;&hVM;i67OZSlwgkYJZDM)eI7ZqlO)gz+{hu9~Py6@LpE$iVz zjOys)lL7T&7)l{M1x-Luo$3&$wa)Cuvt(y%=ZH zC+_e3S?5XL3{!zdTo+V)^7mht)VN7IF@;X3Jzfoak1TH_RDsnY*Qrj@d4l}9o^?nS zGtimP2lJ9KlnGB>P}u%u6=J+rkhfk^PHS<8?%3pEy=a%!rtD9` z{;AQba_*nsns&G9)VK5Xw82#qd|H>p5_kRX{YCq2~bjQk%J%crZK7B#y}@y18r>&DF6GR*#hU2Jkp zC+Ex6ZX&|-4Ufy&nsOq-r-{qwA(oilYTpLg@5tVFZ}5^G&p0HpM=T@-W2Mk*!|z;F z_{xt(){}F?O5~3N5Vq^cMqNgjxT@S62x<+4RSShO=%8p>83pN3* zAsPKG3*)bfE1G+KL}x5M$Te;V8S-@GUcG=q9odo|um2}AOSgUVx*=xZ!ExOMbv0`8 z#mgsy#8*OWP4!So@awtZrZ(2wV@IyCGFqG%=M?qDiGSBo+)Z0`WvCe8{SQYx9{;V# zw$7f;XSS7?t%3Hw*jmm61u9qiTxv)!Yb>4K4l4VOAte03vMp$bR+ANu;_&f3N!yNVe0 zwBmSNk8GmhyYTuj!Z~jfQ>-h#?r6e!rui6z?>M7bDycgN9vtE8f>;}F)zcrD8?GG9U$g8abDEcTu%Y{}Hs>%BEP4X86Y>Mmt90(! z!5gNci5G;Il(h)RD!honvCV;|TOg%LINFhxuLd{=N7j5c|86<)Fz7za^ajbOm}c;k z3yB35-H*8NX!Y_>OcA@q>4GF~ARn7DWkFxKU*u&{5mmLUnA4LQjvn!9?2hNMi=$`q z_sPSafb-$amsfRfd{qWoNEJz;y|=u_K9%l^`52-USmtX=to(=I$=EANs-6y^r;Sw` z7Xs81NgwW9A5Ab-B=3r!qntHxnp}kiz&N z1E7+%w6f>$=R)y(ul#>5&vXP9uSeeW*7E1}1YN>X{1!>Zzv_Ug3wC1qxwRH>60R;^F^5U9w%x& zFxD5(JaxV}*wz?-VqSh8FXv)vyD1oKmaf2|Jo@%>290#k|DY`ppAK`tzp-V+1PIPj z4NV!5iQ7mtLzT!O1CN{XXpC@`KUE__%*iv?EC7EFK&UvEX3}qIR1lDJa~NfcpiqqqH!x$Og!Z=E&hGyEuaX7t5SF8ckQ}kVJ#Ul zI$xSQ=>?k8wPZH@e7yG@GX6^wc~6KP8m|00w;0N8u_;VJdAs7UZ6yoL{k7%wj0c-< zJ}xl+>Vz~}d7ep6DMA&)C5(T*-w+)NA8m6xtc@XC1Vvvx`PwN%Il(k2r=fwbkK+J33d)&-*Pu-4!w;}EuU(Mn(%Ioou_pCD_Yy16CzAJ9X zV^=8<)dS(>SQ$N`U7_~&?{w#lfH7Bwt>cx_@B#5$Bwb96l2x)2v;LH>X!N;OJ@%su zD0;MafUId77_1Jg3H2H=SQ8#Jhx{=3q?O!}UO$iy|1#e_h0GU-fY#Hlp)Q8w;rVXnjfvkT#zI98QsA?&!W^!_&KpWowJ}KY%4()W@;7j zP)j?4aT9-|aU7gItxPHA?Kb@GO{3z8ZBZY0$Co-+Iz(7oTM{R&8>$=HKNN5uOijp> zoBPHNKG?>66;Vk>*zLFYwF2srRjDcS^j3fjL2t#kyEs0i!|FgR2S)|Fj*o4R|-anl6bjf#cf$Ot|v z)rn&66Y^y=$O~3Tzar6 ztPlh4*ew zwKxd|$isfpJk$Rd{+0ps_SivT1{YwvY-e|gC(7SlOBUHS%!Kh}GlID}XYY66e?+rCR`nF~kLslOez42~Sq1U3n^VOZ_ zvLG+3yK%$oaCF)wQlYc^`e;~`2w;uR;z_!QF3Ro+Ih7I|H5!LzUD|zi_yO)~ zHqb|ZUYu3gMjp6{_p@2AikUrsv{`_xk(SnWe=gU_orQ!8L#s_euhdxId*^>rVx^^< zzd1z2}t$vpjNuX`M!v*NuTR{4kXXI4bT1YJ)DTBB^+yM6G^4KY6XNFW{)%x z5dY|75NR9(^19GNimVVHZtMErEu6i`6P-mA)pJqHMmi9XAsKTdA=!=S41BlT+`l+x zd^I(Jn3o08hS}W}cs!&JFIq^-#t6;7tekR|mONr6bK!wTCb$wD)#8GD)stp9jQfxG z>mBW{TXKM{S00A#IE&%Jd8N@XqbpnPr+=GDx6hEd=^@Vi18OK(qlp<+F2jNRSJ`MZ zL8T;{n#ru8^SGhxgrOe3Y8Ag?9Og;`{Nrfy>z#lF?MssF*Ryr4ERJT_I3^tWuU+9m z#%+miu7RIVt0Vmmt|D!FCsU6HxN33NH(ltAwm`1-vzU?IH7TTF(RRyeLf&x6){+d` z$iB;EKdipXsnEa+q9iIo-zZ=i!)!tB&AL9)ZP*m>041KFsws60r$b_ldH)h1Zh1J7~<>#UVjs9rO>Uek~)o@ zNq7(Orj!t^i~4$!L3Bcc;W!{gv{$cso~RtDT+E(_pF8^$G#Di{%9-t+l3P?z*AxIp za{A-Nc8z%v0kHJqU1wXy)7jbEgkIMx?u(?M^cGn^rV_@T{my{W0mq%*5y(bVRfj4- zuO`Hp0=g>9K>ZhX8aq%(6!$ERIE`!zmhBEa2U|b+;@XPwDYZS_%4n@V30H)?l(jTD9BJ0ahqNq4#xTRCdAAgHB~lBaGgxI^v)2Cuav& z8B8$?|2K1aNwVj*ys83WrhT2J-;2;efX!cv6G!zux||Ib<#BAIk*co zb9jGn=({3*X^Wk6Jm{|a+foDCgLmQKL@JJw0y(Xo0?n`E5(dw3evpP398<4!zHoBo zCN0|o-hCh8Q9AQ+f;xJ1H0*qWfY&rk?>^M4bh=kzAj0GByP^5an(bM-)SKg)s~Lin z2<+{Ef{-LQhc#POllL@tT9ssYR7daUtuv{!?{FDP(OLu9JeYY&?wg%|5#0LH>l;9j z;@eLZZ%BfoYt}{rAw2u@bu*WV3&65~U1uLH70Gb#%bDI;vf{hul(q+W&%wr`l49|& zrrNHmX`^PBn{&dBC8H_Y9+^3rdzpq(_8f55g6?P{puLn6A1_M25o!)O2*%YiW1%2Y zc}M&ek!;tQrB|PJTGcc{g1oOi8XafyNIN%r>(UH^o?ktPv@~z*U9kuOM!V=4J+>%& zY!wq5X{Xbu-CxZ^g*2rlc=?%5{UDOGLo8M+(vuy|+?^sh{%V_++8%q)o6h&sb=y02 zytQUU7A^z^8B))9D|@jB{6zK!q*%v$UA?Z#khmChi}cpl!m(n2@Z|aR6SentQZVNV z>cMMLq)K|{gL{^-z)3EMY|G=!LL1Ti(f4NDI@8q$Xb7Jc87f{AHx1ZsS$>`iA)E&$ z>R@9O5Q@(CXN7M$tiL~NgxYJeCh91pG$oL1dvxY3YP}ym8}x)lKrd(M?B<_&_w`J? z|5ZbZ-M;bY&j+1nhp`ui^$*xjnyc={n`1!ag9;?a^9oG8G`g~YRQ<;fbWpuVKOY^Wx$%!0W9qi3!LX^P;{jwW?)FEk$XPL9QN>J}Om%q9 z7)E?8g;w}i7-kh9Dzwoif(k69YnXFBeEPDsEvMb|c)KNE{5HZ%#Wlp?g^g47dKgj2 zvf_MgG9V>2*?E0xZUk8Qlvm+TZ|}e><#VO0H%2NtTrR3!Z_ulZg0yX4Cnvn&*_CzM z-X4J}2igR-VlJ|#kF*D1)~YJrv=2(YmRpcLxu^fFu`j2$>L-^_NEf=7T~WBq;p;<= zX;DZm0c(Ce$oLqXw>ls7O}G0Jd6^7Z9!N>tnV{uBWdi=Gx_>#R2eTU&EeA)U{-m`1 zx7<2s$@j^W-2g5T=^P-BM4(H1ncFU4M<%r&20%f#O9ZS$4{)ax#3k=gt zyMC&E3E);s{*}9iqwMX$3|~`a%i(cJv)5mxbv$X!6-G@IV3xJbFv9IKy$QZ69SK*3RnG%-ur0%m^9 zfd+`wp1u28ZIN2rf?*g+3%3Rax21}$C%#*Mt@%2C(@-HWmtv8of0(m&nxF%n{pO|Qq)Sg~<{jY}pGuxdx)gLY&tspamqDi^YDWo_5lbJ_4( ztpDO&pQz4%d&P7eXTCgCU$-?ysPSnR+pHstWABb`TnJrSifn)iU7dS(w)p4&SU$fK z>moGv-ovkVm^#vt5Dhq6um^p8T-2CrM#a$85@Cx-xGU9uf}Jp-=9W-Svbj`2j{gC`E^<#~*gq z0XC(49hk1&qtIF;_Lda=t6`^gnw#NwXtkGfteM!|p5O}-cK#VpKm?=DUH+DMJA*IC zY!TAiRF~$WMRt_6_5=AkAuOj??7Wx+|Cm(ZM@UWH?@SxW{EKP7)UkA022|+Azr0mU z3SP5ZRW{{n!0%MVDA19{hGv_3?J-!aw-Uu^b`&uT@p%#LQVi;8su*fag`9CAnqHgGXBT=d!NNiudwSUL5WOI7rU z=61y~hO4gd({B{f<))MELBo=1jljiefQC;=z4{fHGcSOeq}VU(5Qw`Pz&>(>`lQ*& zsV$D52FF;@67%{H|E$Q()?Bp_d=zby<(H{sdEdFAL9eMkzz{LBSO%n}`7(#Y$NseQ z*g%3fXRVRew1n^hisRt9<}7U6r~@C=%)P^}bX1nI+7ueT&6lhEGPXJ0zooQ0z;)cBJ0HaPer1?af}q}7mo};W3ez-1Mkz5e!xkYg>vIN zz#rAeWI)bDO&=pL+(X*|)9qf=Xe{@Tufk(wvXO$;LAoQQ>|Jntm7cr0xnK7D%{G{x_XN$Uu z=ZHz$8APB)qmUb&^R0ZX;SiQ2*wt0J69zPr*5jTq@kBP!&Lvuj6E{PwJ3A8wz9xX2@TM z=%L5u?J23>)0rZV1G|7t84uT8b!K63Qs+E{fGl^#5;pqQn0gzRj%$NpPR|U}C++6$ zTV(9iLsd;vz`jNdHca+#yulXXyX#h~{;dtKa*PHocEb+X11DTuPbt~ej-9Py^tN82 zpPE5YFraJUWlI}kFn+;Axp2(NNov27-)T9LZH-P|7AE^FZv_wcCZMW%`6?pd#Q3)> zZYuYkNw_Wj$|99_ZlDXAwas>@fn1dD1Bj^(v#LQePr&of25NGEP&lRM9gI;cdXZUb z%P{RajX}|a?(UgaWY}G1+2xbHnch+RpyPrUPjKFC(iVT>n8jq!>SICOd+l)}xq7T4 zrUg#(Au;zJrPrT2%=s# z+~_ee*eQac+ub3f++4hN3#ikVxW~QC%mOk9#s$v^fjv%EL+mnUcD7GP>iLT4?tE~}equ5Er3mv60E3!vDv z6&A!9f4ho*`i!%#)^1D!!~y0tgs2e-_38q^=L7$xEY!uQ0&RM!62&~Ct1ui7;NTi1 z)?U|zp;-sSi?w(wH~p2qS&FPKBZ2XjhGwFjx2%2c35g?uc<=Z6_s^*FbGD1Z@mtTC zjP=aTXZ*%(pk52djxbsK^Q3v_2feei&TqGT#`*;a5HS6j(9#P;U#WNWycKTpOHd8P zf>fN3_2JYCc0AGZW1-$$`n=pbEMmLlSduaPe=O$d>#J|Gwn*xlMr#@`dT&e~Zwb+A zp37)$iXvh3S^s{7UbwAlUJB)}dbc*9Y~Qq~TQ}2G8}^PbT5(G0l&lJkykC+TS&MrX zz5j};{Hv+VuZ;WNSHqzUdhy#MsyH+@VsfHiXmU?yiMXC-vLHx8{NT>44{M2>vf?_* zjKIPk9t-4?LS<-}=5JV55#j%R#&Rk6+2GTiFBSJQJoqs}?`5$9$a}J#^5J1`4meBJ z{K%qEe3T0~kOqRpLDj#)&s!cHy9QeMp0lN}pNQ`^3Qt}@$Yg+RAtj6(!|t;CZqCB5 zNPW#r_14#BE~TGETFdVjWlIg3Dj_arBy?VEFit>*qK)2xJTu!r^env{|L|~&Uo|%J zlW2MB$D?&dW269r-l}6xc2}k3Y1B02`W7^kOvmtX|7o<#BxS5P@;*(+rrA05bx2-M zV$RxK3I6k3?*R>@7R>Z=!05bPq_$>dZGrERZ>Vq&AITmKvF*kzcHKhQ^4ZV1SuVF; z*UpTXYb(T6GJpl~;J&hklbz(zZ^tFFsvDh%5U3^$S^fU@?q-f+wkb}xf{%zIW(lq2 z^%xxUIP1Ss(}HUz;EfQx8IfI$=OOA;tazqTOsu3zvsy8|;O4Iyl;A%aU%I@IiMKaB zA<0YrPI6m|XeCZ67@vn9)nG&I*9Xij`ohC%B~2%PV8&@)D=kkmuSXB}7SY#BvU=!6 zjhKWveGi&~4^s?WEIWH97e2{Te9%7ekakaJi~5g@c&Dc*41;tcu>Wse)q;Y4??MgVTfMyc@`?j#St^t zYiZ=x9s4o1wg6R0KFJY#9gqbaGE8AH8Fj@yA9yOf_7weQ!0xSR61dq=l3``n+rR#l zGNPuL>G&-dv4BLVq}P1OZ-qJ>F|nrsPU~@n&0aCV zZoR};Lfeh+^W~tg)pVW^`}3)MPynp?wSYJ|VTkp;kqP&jR#8q*ey`kkGWSk`YBJk9 z^|Gg4$qp7)po7X!?L|Lszm&h}cp6%x;;fO&4Ngc=+J(t`|aG|obA z?PyjcBc{I@ml55@{&dKZ98q!5s=tF&yP_lsqwITcs#YTP@Tcb6cI9)FR9{vuRa5i-y8iEyKTbP|Pxt#dn{A@><8W3;@>oe& zI!6(KnZkW&qKWk*tXVq$AB)?>=FM*j?h66Iv+adg+1tN0$#t3;{#XjG!Y8}fs|p$* zC+_Xij}Oipf2mM^05?F$znzHBKwh!ExJdAiE1tDDg~e2n;>&?rkbZ%boW1-CDzH2C z4+i&l@S@wUqM6QGJ7x<)VKI)PKiMh& zHl7mcg__q2($rcCQ4~|{N2~33f@(q!(6dXghHF+T7q3`y)!k~dep zF39idish!{PFx9=b$j3U&-2iqy0yL|$s^nLQQsYh#lI{4`M5AiC0B4H0gLs(-}-KT z7H)pGk;l%?rLKaO%9CGj1()txE$QT+t2n=qQ|D211ASKSA!vr*NUPLM)=!y#RDEEo zorE@P^8Y^f`Bfz;?D%iwF>Pw|{=~FP)A%C5M|FjglymRmx|227)e0&%XP4U24H8%F zw}8F0+*z24hR*(r5E3%5>9_>?FCot?{=R9T&2TNWeVKkU(tq^`7ztH})bdrTdjZCq z^d~h+x*_np7_l`wp`%0P$B$6OrYBVbnz7}3@vbC)i}K*$4KB8Mn*sniuWjb@#+o9*XV@2_-iuVbNFV5529UFR4!gr?IMa9TTf%J7tp}gjx{hv`kN>L_MC9#Wo>Elw!8Wf4Rba#%H@- zQ4_$k#uGdkNwH7nZ)8bkw`ehdg8Kq|-J@ww${w606m@HT`e!9F{`%Upp_cyUCfVeq zbR(eYy6vQlKbKk3Yf%Q2YPx9_F%n%!HHX~NqT=|bl622P$UMQ}L|9nMn;ufTvVFgR z9{xG{`lN=}o!=f)Cite%nq98CK)Zy4lfXn$tSo-MSBQRSDB_s7JXK9nL5%96_Cb1d z#*!fJS!n1~JV$Aa+N|lEOzoU`{x%wyVL>f(e8-o=k*m<3(I2Z^{)2Kr6lYD}*h&vf zDS6QeL4BT|ftHmC??^bmoLim!i!-fWYo?zxxj)N)4{={h^O(G!ocgn50R(k0RCc1G zSK06OOdg!~HTRfKE_G-NITA6-gOVM!%$vZO5Xt)x4%PE2_Qy{~+*iQm>O3ZVbs)Vo z9<`bniO#O101wmY4ZR6h3O2m|hs{c1_Os z1wLiF%yNIadAjc=(XKSDZC`TWDpH|n@MD#CIE7A>c=X%50nZYxStXpt8UBtcllT|( z0!6xCd}_(qKzFp|pUpBH>xT!T$4{ODPC7vzDI-1rJ?I!tf<>HUj33|(kC&)@C%;pl zNX+_j$In2Oj_1A83w^8a7|%lEooRD&E64XG#`_&})k-N}(()-?*-K)mDLR_Li+a6~ zJiyO?T^60H>5~65Jd@y|BspcPOLHVhFUW_MBx@^1E<+%8(UXdQx%UP<@Nc7udSz%)Pzu?@9vh8WnW~!!P#-&?;|gv?PNYwa3Fj7rnDVE0Adb zMYGr;ovzrMmyx3`5Lk8(q(z38R?rlQhuZLd6m7~5C4uD?wwy!^T$<7)64Cqq=P?Rj z^ae3T+eW}dvndmxW?xfv+?jqILLAwD8KW2B#+n>Hp);p38ttKdDOayan_{BjN%#L8 zA0)Pl?tB{j)%H&kxoTmy>ol`ii4V>ie5JG2)2SXa$z#QAg~`?cAJlu^Lev4}j%{XRRn&hO0J}!E?ASp~ zU6LNWWm}Qn;UST|c5{)2=5|gPnfu_@ONQ@Stsgy(%euTnCcTKSU#iTXyy_{a#MjR5 z!Q59Ban^Xl`qt&y^dvN3b&Q0*ft$bJEkxX5DUiaBF;|8-E?jwXNhW~uQC{T<{CitGrcM_)y{7-q(u}p{ETRlL7iS88br`g%ssr1CS8Urs_X_#Kp0hT+PhlTX zCnR1$SgONHTg2TVIR*FK_nFnP-UKavb954NVdHFAsoK)W)WB1<*j^n21 z*ewy>j{MlF=p)fwnlQsuxKYmurtT%Q-h=_8ZxRVE!jyXd)Eg5wfBZ6M7LVDy=0iAn zPN875XvzhKNG>2n@$U)D$y4^N=iV8wu0{!4>h6=xq~lwpSj=S^V1EatFwoP-RGp9p zFP?6}1=|6di29B?f$N>HTft?~eP{jfr0Z44jH7ovCL>!3#^CI+myXnvo^_ zE@aW4=`$yZn>tvS<=wb&vyd4LEDy#pyCusscPL`6och_MLlZK&m32CEHrlSiIOhe| zKBhHSX*WT&I^d=&y;bQHA#pR058_d!J`$E*R;**<()+uYJN5WqK=I3KcbDGqHd0Xe z8LY~aA2JniaXi|wjvkKzP@w6Ge61v9!6(2})y`13_aGRjrKnLWyvn$LmsGB;ex=Pil!<>TOmH-A6Y_4@D6rUr}|f&tPO0lwrW$~LH%XSU7ZhaezLuXJMZW|q?IJW zMn%yKV`5&(t!%8`?UHr>I3E(W)2(0hL3I9imr_;q?9Sh{nD~@f3uIO~!EwgqOB3|PaDdY;=p4j=1Vs%hqMMjE#0hW1-G^O^yj#pMjPr{0Nzvc8wDp^c!Ng5m-V`zNQ$M)KcmL%UN$02Uv zx=GO!Kku(`S!@D!AIw2}#c!c}4dJ8h*n_@q1If7ZaB(+iEwE)sGb-W}%zRU?Hf9$> zI4KWAHI48E_u5Og=xqXAk7kKZtGdid|-ag&jCxXF78>C zcSJhG)bFU95)#sD{KGX(LU{^0e-s#Zm&31(`skHSTU=_gP#Vd;Bvx*8C0SRivm*xx znHe4ynccqPk```Gv{s$GJQG+kGxlAGi9uiO@~LQ^)oLb^1cAYhX>)gh>X_BI=Or`| z`U?eS2G2vCY)hU)z{XtCmCO4SoAe!f-+>U$s3`fv+s=nKVeD8Rt;%i0t1A*o6TW=N zf>^Bi_u&jXJ>^9DXk!DhL%pY;eZ~=u5ntis*9o~%Xkp?X$O>HDE=6nXE~kC}Wn0^L zhF1t!rdNZ*5-y;`=P4$^Kl59P1gvZ150yS?5btaBqNMAHXXPD6Q^2S#yNjgy^K+Rm zV)DrH$)f<`@uDmk@#QH%bl;J<1-| zIOy-)rKt|+COFnVupzK~)Y3FEjIVdF)dK@I_m&@B|3K*+P+_ANJo)#Qr7wvp?kc$I z2zno+77Q;5==A*znpE%t!G)rf=WsR0Inv17;&!+W+Nc6Qm~4>C&zlTAR+zeq&o$9D zKD(7I4ym9o>qg&lHZ3)NTbQde5AEt@r*Cthok!cPCzAVhTK6c?DR<*KHt-xm98%hB zBaEla-glz34%0odr9Z}Cs};c9{u+3T6Vo03B_2HML};IInLf|zDoooH;?yq2t8FQ_ zwtot-Xo`^|(ky}XK@K16(1qHR>~F%0=!T;SH_$rf&QC&8xW?j^X{lk+0rP8+=KTDI z5JrV^esJs&UaZ?k9-H=qBcoa?qxyk$3EuJR-vbGU7cOX#EQ^N*@+}H|+R{39WvqOE z-7k~-w6e3DZa|VGoVpYrK1Qi>_C&oKVuBzaD)z4p^%v$<00b_36S9K#_~(C`d@q`o z-5s;{HJ&QzPB;#+IB5jL^)m!7z73Zy;;xUtUV-Ym=-m|xJbj}Wv=p!lV9}IjAIADx z&AcmXo{+<`z2w8-5G;N7M1RH9x`?LViu)H` zpj1#+{JTBH@}JoUjmyub-3vujRjs-kMb}_Dg>o{EDt^~gw`=bNNncK-K4 zs@@&bSnH9T9=uUjSPP~8`BJE(F@56jy@Kw0oxrzQfNTve&ZVW6NNUkUTamfH7V-)j zrcjorZ-0+0r!+y=dtTAlNNvkXUoKDy@@lVledsDd2o8mgh+8dfq*x0}I7Iej&T)!s z)l!I20oCynLI-?lIeW@zwqQd`fyA9Am3Or%PU^dkw}i&}zkJSda(Rv(--Aa1G5ou2J(d(G}u+M4Poxu|9qhjA@s9 zg+FDq)O5O7pYHVXvBjYWy8%}k5mbpE`slqf>&S0(f%D0{E40uSL@w09wyG8&Sz9sN zZ=%WGhmMxZq51t1b4#^-b%LRRqp@)VW;1{&3~bz~?0W4Q#c?um6m^36mc`9gs($gt zu109QPwvt}GP0EIwTq@Od&fQ0z6j1!Q(>Q{V#4{Jm%!MBP?`^JJ@I|*j;0*zF_$Vt zqC)h0a@Rn(T5{vL%5Ij#rQr_!&__Il1IKUq@LEmwV`Kih zoFubmFBg_OJVInA>C_4S2|AvUJ7c(oLRnWXxDW;Ar|*@}g-rYfrvV=VZ2jqj5FWJ| zq2{q$s25@4QM1v+^$wlPFpR`~0BI$x;(QK%~n$JMUK*Nx}t|zKLWGE z(^DjgCh7uG$S(Zq)?r+0j(FfN3*SR4a&(6n_(SyPEtM7jX)q|f>lKu6EiyX6q;()}kxX%(xa zO;l-IUq3o<^jUS(*fUXdy%uR-#qySM?-pJHo3=sd44HmPDcafS<|^hDk7p&NlnOBh zn0yu-YtPZ`nhQ?X%Tnr|Hks_L-*@qLdJ$FEO2+19`Ana zAg%}WQ#hoZvvkk>PSxgXlSq-C{`V&Jy375Iy0W(buRGYoG`N)Stg{?X#4{Jnjao`p z`jm(V+gEp0YrR~mc$w9Ph$PD=RQXUYGe-F{Oo8n7=sv!L<^R?F)&uh&rXkCczX8owa z`~fkEY_-?%c)|D8knWQbsQI1mr)iR;H*U2KVfGZ{;PO-!)LE|?Wp)9oHQP7!<#-ky z7AKvmqvC7!y<*MLM6-NLbfjH&7nCVe`s$OD%w&6nY`AP14Wx}|`dAnc4_fy)jUlKX zgpfD`Cb!wx5}ir;F;`qDj%>2*gM#=6E#Z%B)2%hDg#Fk>r@8e|;y!o zAG$Ls<3*5t= zCEM3l1gqW$l}oM3*!tJK6;IM*S}j6EpHzR!3tlImJ=vAn z(w#rntWEumAIf|$)Dq05Iha`rEc$BX+~|vZDt%0{x$AXV_x(3;hjYuXSUG$Efq}d> zk=XfxsmL}VS_nLI8(XRjggNglrs$G3Nt$UI@p|Tq&J~o; zN8h1^QdCm-a|=ZyT1)#g0)B^=xG@zJ>p+?-rZ5R?R2~yLfh&|0IDe~V8oTSRDraz< zyX%%OpbU~0V2jT#T8z=M2x64^&t*k1YX%%#B{pBJ2Ch09f$ycf5Cex$L&K~YZnDk zri6KcDh1+N3;QMAGl41?f#UJ*fOxTap}bn{W)6yD_D`b@OADGM;H)x%Vj?ZW`ZGb~ zL3HSA(i;gUbM2eAOvpl>YrA@*PL$5+rcz}Z3Z+3obc!>^i-cW6kpTzbtRo zBux6$@w6{+rh8F8ih%Zi7A-Ceaqn>0R5*{^eZNJs|L2Yh3_f3{?EvYJoBSPmXj6Gu z_wrHqAr=Bco4^Nj}l1;JT^16SuIZrg8lT`xeu7%xIbhCqQosGVDyfUfq znI{4=8_W!@IsPBY5Ymt4*lwc_eLlt|QyYa_Ux2xhlyWE1uiA4I{VXJRLXdFMD2`n| z7oj?h1&5g2UsL!Z!w5@0VUKwXPb9^t&13zd(SG6J**JH+LQ1=Aeb{>sd`RuDCIT3X zqvV}Pgt%;kLuyw>DXWkRn&w9$RqkF1>8P4B+Hw|i=6C;43(@CZrdr!M6l~vn8wmQ#Y*@O;R)kt@SOGBJac<8yG^h5Vj z!D-BFez2CpJCVvAg`A?y;CE{!1lP4;AN?i-Cx^E6wa^z;P6@70MpR?#k6KitE|fy^ zH<5#$OYObBDURfzU~jICNBTR;;1lPmX_^EO8y~6rVC^+ypAA)=ic!hG3hb^?rMA=K z)>!6(y?4q3+Ym~MZ6bQtc^f(b>FgJ!LJUgyNpEGR+N$Voa@5Du{*le?Di{O{!PAE) zS91JD90ibW93E6|)TfxQbhX1&$r}9kGmDtUMXjMUF^Eb|bulR#d-Fbn^~P9l8vLG0 zOYV<V#Vv!~JWueIJsB`?e&{~rbB z{m6#mc5zB+YjjYXR_)qiC00>ejG~A=gV>2ZT2)l-Es5B(Bx=OwYqVy>j_p=UB34_g zrQ^Q${SVF$=bY#BoEyZ};`uZgaV1(}x`Od|eU@_Pv(F!=FcPf19TDo-QQ~LmiH=+H z<=-nD!)z(a9?CD6AJjHo)qm;{oD`cCs{vfLAt%_85dPmv1Ml|V`^Y3X7!fd23U}+B+p>&hp~~!p-(|r7j!)(+E`258+A~YbNQQcY18jO zN)OmQqEmPw)i`!DavP+;8y(Smk9Znln@*U{dJ)mPa6T|PQv5&li1IVdAkSt{{KD{0 zHj$8<<)hImN?#l>H|uysTUi69=}K*h@H~z7IMK^5PO{izt}VZC>d{+PeNX@n33>}# zI_$cc>my|@!3esxoZv}HM3Rb8;$Se7cOyZf6jk_wPog9MM?R==t2`Y2ve_P8MG_kC zfT>lAeM4Q7cU;^fQD17~d6roD)A!EXqw_{>K5k(La(wSio3IJRH2d8x_ndCzZ*jao z1?^aTpkLKdX8*s3dTW<`*WbC;W=n48)xH#9pJ?C!T6a9Gy`_T`NpFG0#F^`Xp+Ky) z*X8enJ$zXoWrX}=V<)*Mkp!`9Pu7tTUefo*)p@xd7_%J6j%Q#E9X~Xi!jx*=Hj{1& zJv{I{JhBi!;|zXW8^mxLUZ05*=9aFBrFqk7u3FxeeI#MVARuMjJ{Sq@@x9S# zA~aKow(Iyb_If@tRQA_bWa5JMZ;rcCbN9aD*rPy(*$Hge!3d29@!tH3}`= zo*EG!!|5&gPSL)(6DlztsJ_8jFJM7a;`E*RwhBArRk;N=N8 zvvX?Ci~1gKX6O^L_w#lK*4#_+u;`oh684Kn9*XwuR~q#lqA;Q8<(bPUYF$Ll3WrVa z{)|1c26;3sy&umMs{mNRcEL_+F+Xy zw-Sl+&I*Wf-2VmM{$2bA?jjqs2vce)kSXTu85IHV7<=2lOyKNM6l-8qJX_ahY??zt zsF&B3UT+eQ^XOF`PMkUcyT`4RvQcOeii7yU_5Sluj%_9ab85$pQ>;2Kd8M^E4c0snI!sQxWpMJ+~)_Z?iyUh?` zrBRH;PiUplo|o?P;~q$UrjU_KE~>28w`MvrRsu74z@fq|}N? zH)S0I+cb)T>(>5gviLgRZ1R?D1>jw5#;RFPq2qKPQ%wB1_5Hsqnu~1z;jT$!XK^&A zQxaockrLYp&;zwYPxxu` za|9>oUm8;qwWg_TO0MsFJhK~g*>*}bM%Ulis>Hn1X1ioGIgXvLn7}EORI;nPI^S7U z`TLaG57W#K>G!zh1obOJ9&wQ2xGRY%hJ6M>Nr!&<#D4s0T`%X5<0#&SY>=ht*~tgh z-H#5+&1+OA_wa5NAJs-UP|dNS^2q6|pmNk*C1;3}EbD=yQph9ZJI_Kf*b}(Tjwsp9 z%-&XBR+)1e)(DO;c23ItCEpkw;qESju*J}42EG>Hotv&ZmG20JdS6H{&~e^7wV_xO zgMKVw^b%gP5!>Ll7IQ)%>B-BA>d+|dLg}+h>fyMYf%$;FPD_rNRyFvAS-F+jp z8oC6shm+Dq4$iB9fu0oo=5x~&Y5^oyW{E%2d;z-b8|ZA*9h^KcYj$N+CjV@7hYG(}5!EzG~I z+|-#WFgHns18LLRj0zuQr7xQ%s;Vp85X?z@#GQV~%WzwT{?b^jOV}Lb_*sbXkBR4% za0tQng%<2ac4m+qc~7r(NQF2bKmUH13xn=c?{y=m2S$J`e*Iim-rBb8H z!y!}FLuT|`+icF=o!;WUzXs1K4%1O-j>2J@-1qb2}8%n`9NyG2N zjtN5kZqmx--UV_1)NcAczk$cnNpVkLRG_}86GPL}oLvuKGS=|8Od zZ$<@jJ7mdw{#U3MXA!vN-PgZQQ|^{tQ8&S~?RUdOf74(Rp(6;q$^ z4)4U`4g{%nU4Jvi$`|jTQluCrPfM)bz@iK>sf|^8(*xe6gT$WT#-@dAVaLj8`S!oU zQyPKSqlokh*F1queu*L>oKtR!K@FOI{65{&KE#(3jswem$6>-(@s*jT^Tg+V(p&Q# zZ6#?!o*DII;~od&;L#wvWU6qvN++OncGQ(4`3Vy}KH<7OkH{AT9ugdNeG8Mx#Ld^@ zD1|^-VDteM=~Q(AX4vDYlMObYSB6iyE_ybYq6dcX8V#40Fo$=<*vG}89wrk~)Aw&+ z)91weo+8R#0mbrq0@gDoT7u7ZGR4Bt6BkY&7iy)}h2tw?3fdpv>+h@OLIJ07;eAVFOVkl7yGUa2cUfNB^% zyuUX-AWCQ4;jro)^_GVQ-`lI*=Lp#21KvRqmIjO^Yd=L z)0uiIy;NKh&%K{7c@eDpKSD$}JZhuts z2}s8fZRWjj=pr=lI6BKMk-L(-5|ub9n}zB-B`j+|G)SS{M?HRZmbyL`cWT|g>9+nn zO7ni}=@C=S&^JC2)GZ}?%9GmT4{-V9;usO?ZINapy6UzVIT&f?@spa|La zt)lWh@!ilXZj~zkZ-R3r2enEV@glL-p;Nxk-JS+{_sl8D_*#(V?s@#XzoYl2!^)f< zSr9Y{tpGNJkz0~Z0?E<#GOob{?ksZr;!6$f@}9C;*6~?Q*Z9Kmi=* zWsq{#A#)yJ~lNur-Wn~`Zc0JosYeGB1#U;@(f-rvS-cn`v<3f*yAweCT>z>#nUB6qUXod&nsx%?PVmsO+8!OxpW6X~&cW zIGa<#RXIuEJI<_t95x_ZkgrT|52{l_4Rfrw0W;#OYrU_q5FMc>7Zk;0x(68zCAa^8 z3N!c~vg)-nw8c1(4CR8ACaVB?OUPVi!O_>4;d@zF$&!{%@6>lXb=HUI#k4Ukz$p+8 ziWw+7Ywzg{7fYrF8fz?ce+dv90VZGhMU-WNgS59Xf!%ux{ajqVx`l9*vhy(`XL-LP z-MG^p5M~?2@VO{}Qx8}d)jjz=_^P>We{ore`MmY`OR07VEatYLIB>jrMgwjIA)+|d zPw2)230^^)v%i$WXB<2#BjiNk8A3CvvxS}Wt-QMaWuiimOuy!QXH@|+M8%{_k)UTR z`Mlzb{(QoMTF?|-XkUfh*B?}Uyf4Abpc)MvXGRFn*=i) z-$49ITNjzpN)N8@Y_-*<)<-!nnwMsE-j6Mz7N%XhzWT6CWU{WL?(Glby9rXB)kGfB zS^|{Gb>_+Ucl?bQH$0qc9F204n1qNG{GERjcF!&sruWA9Z|m>eqwx(4J^OjJc#DD$ z$EU|47?t`EselYO`pfN$grX+V%1hEBSK7{3efu1o}#CuE^PUFDgGni9Ty9WmA0*fT{87|A6^6sMVWN=P=Nw z_6C|)cf85&3O6vXPPH_??EC{R+%F1<Rdnc5d)2vfu)~-6Y4k*?jUlC1U!o3emc?MxXI%4v5%zF7O4!TWcZj^ zQ{Mb#ZdMs!cNEZONgVBxKvs-q#ov!g-AJZ01AYPLXTzj#9tr_RG-m zZVIxBsDX`hAss7f%qo5|AlP!S zrsTHSOnC!{?fnei)lIpaZmX5ivm?aP^DW){jb6J+T*-C+!@1AyL+^ICvbo(lUapi0 zwpVlr>QVze%hX0I3I(wm5Ze5|rk~lY;h>(NFwNL$Ea`~jdAkxRgm2Sv-g?vO4s<^3 zm3Vr+w;87r9Rx)ikXpLhv|3~;R?pqMa_z>a=?GXGA3_+-g}#A` z^nrsdI%eqLVU)ZiKdMftBJFfWV&GMfQOJ1Iv~Om#2Nv2$n*9DH26g|7_L%U#a{Z@Y zvu!!2Q>7ToGXy+LGisE+nK`VETFdT+xG>(va#8czJC$W@KOBjSf=@j+6Cqm z4l#ImMFoagGWUI9s8Q{e?i$YR9BfBWZZ{Og4E=d>U9-_xHc2DTv7)BzY}sJ%iRI*;)C1^r)LpCT^j zb_=Q948Jnl+4E-qn>wnli0$m;FbTnVhxnLDxirPY2{^ZAOl_;Q zvOLz?^^s=STpMaS!S3_au%;>1LMCah`Wq1;?RCk@x@q`OCwv8Y={xT%*cnU5_94?s zC|qXl@t8KE{8=|gW5^fE<(l`8@JX(=GtmF)^Cb(nj|z&0=m`@rJukuaB$h8=f64nd zQ1v%IpK$c(4~8hCuMh|TL?40wyVpl5+A^OD45;thjJrQ zU*i`4`%kqZHO-jMR!%eZ+fUe>Zq|tqU&A@jLz4H)13?g(^B#yDGH}j z3O}lxv-yriLm?OEu&{VI3Q)O`bvCDbYGBybDaLTShdzMLr{k%$_iT^V3N0YsEKkd|TXb z#}5+dHT`_2z3gf^4j)C%+=@ZpYGmdmrZxRM%%=yKGWioypT>454wzX?uUA3x21!7Y9}L<1gc_sNuYA*ya|1;--N^3PuPMb* zZ4!#ugMaQ!@+FkKBpHTGG~l-3bIN7p(NMzpiSiJc!Rud|ip5QpbhFV8j$l?diXBw7 zdhvMldQrkoAWF=%b53iV>z}H)DPX%=-FLE7SBxSGnLfE3IcCqp2ulyXrhJQH+$+9n=|Q-P_ePjH0GGDPcp zE@tT*MI76A1lY7w>~(-XGQ4*G9B&ycSJqco~Umd2&9Vd)S(TZLt9 zC9z$P&`(u{58q9I?6~9`;6}g};DgNw1Eqol@8!hfYkFRywH&QAXhi|nu?|=EM&zqv z+{-*6$OHp62vitk?{2pe`{Qo=RXk~8=*|`46ZahROTI;MGcPlUC1mxqL|EX_YRMDk zJ1WiIM50>G5+RCrQDKltl)^oo^oN ztmfrnzH>LDP#|29w=ZFs>V{VXp;N^&11?DId(A?BnEbl99!jVS6(^g)p7(gcAO;c- zxnFa4J`@&Q*TG$XDx7~!i6^SMppNruCV1!~M}$VAUwtGy?73u`FBnCI;9mc(`?D6&kx@%-s|(8vWh~4i z+V69MzD6<^?m~`$Gf^PQXbbl^eiL=n^m)Hv^d=U{x~Hog^O*navBta5vB18xkRWS& zqPK5!&%Gh??2+EvGQO#k?aVcJ%U_iAa%S5m3@P8*)R8r!L7iwFUS+_7c?h#QDJH@)$XSN3hi5LT-rH`%PM692=dae_7w_^6ZN`r59 z-jIx6J?jxE?x=Gg%wH_GJTP*%d&}0{fUw)R(qQ}eb1N*CT-eCd^8UgA>-#ym&856c zB)p|jqXCCdswpd!aar{4ak9+wD$BE$OIlc6dig35HU8u}3tGv6^i&Lk7)pe^enK&4feGh%B)2)- zSp+tbZU^02FT*@izTvvP3H>M>hH;cy}NkNbSn?y>lgt5j~BlYh0)@oZEVD^%~x z-m{|>!rw-pqnqb;V+fI_(l^j+S1RPY43N4e0F(&J2kwtNMzk)a=F9Yo-A0bq?)*{f z)j~BKCp;9v$qKF0&%NWYZ+|Ld_e%g(<(2NS(-UYG_R?GU8T*8$$65gI#@Rr3O)bwS zd4I2rgCU%YRHg7QLzPE~q<12yAqPvjYqx-yG>Q!#8G0bdGv_m-$^@@|AR~OK0QQNR zu#J?iOL&N;6B|M4EyEq#^~65CukVI3@NSN*P61ugqVUQKm2* zl0hH3 zipLeSoSJ7CNo{!=K~GG7iS`_5t6)0#^m|sfV!PMUFb=BHy>l2CkFV8sLHEbDq8MLX zPl&cd%e0RL^N{gJiScEl{$VOo?`1Xfo2a4j^*cmI@499%0_zm4^x$dBbrg9~dD>rz z36we}P2IuHzunt0v)q(#*uN0PJI}ub6HDhYZzx8>@kZVGJ!+Eck{(ak=CrOM^9>r2 zfom9RYiL-OjPR&sNHah;qFW5DTk-2DN8wcNQ}RxnR?Mi=Vh!_KYxf7zMr6&?rq1fW z|DmGX6l94Nby+5Aw<-EEr_p}ts&uB5Tvmc=$uConsh{T5{{h)22PzVV!W^1dR%5T! zq2wR)&;18U{4kiZur*{~(|=($j)l2|M`WjK+4T2V?%>JpR?qOAkKx{5YY)QCE85%= zNO#lsY6scF3Wz9<>5?Xx7%j%%aZdyKsCz+oZMs1r`1_Y+212R2Hu}b1#h@1pG@-iF z`&&})#$f_Yl9wGniP>%-%xwJ87wD|r7F3)k4SN$K&{M)LB*v2AUATA*$p`VPn&3Y@ zlhZ;cMo9X-Rb0h!I2$R?k6&Xz;OOf*&H3)*L}EDkK9U!LpAM2z3S4s>svAT$Ja(c3 z_^67GJ2Z+WWCylrr78`ES5(p)Pg@`i@?8y;bLJG%;$RrAr*r!*4$Y0UzyzA|s7Znd zzish6!es1?Qze*#^qojDXI{xy8T0v{4b-i6=8~z&K>PzKcw@hN3Gdw2M7*QYy55p) zsrBht9EdD)b-Uk3Is?(26X>R^alLot098P$zj!LCjhP|`Tu@u!QF^W@Qp{)t98eh| zsuYz8#_ReA_|8}@KyJ43DQw{#ma%v!-olkjS3AO`LNrWln{nztTz*_uMo+E7SB5i{ z#z{JzfAJ}lCoG*N{k|HJ4(GHf?Je688z~AG@CET4`9>?MvwbO4>YKYtBrtmv#{^>; zxwQfgT?!c0zn1^d-#ZNDB#%3N3hV1pS@->ZZ~mMkqYegH5-5=IQ0Q54`vsx0@YN*Q<14UdhIzCw(=K$2Q>v!Hg7tA4RTYjl}?Pcqa07hU0{sIyI z4%0zI17W<<9~1i5)NluC!fd{2ip&PdMuVKc~d0EV$TH+b%Udri)@+j2!UIJuDpLq%lD3<%hT5 zo39*eF8PmePgIo_rQsp1fTN&e%|xn+-IOnY_cD%peG=qIiY?c`JiX7Y5FBLhV}P-P z+5i5RW+z%jAaPJ)G{InJIN=!e-eyH>g$x6-^7wui{0%Xy~n#Rm>Ho$Bi(@Q~u) zK1sOY-(-%})$t<%0JVLRN?KC0Z+S8ZxsX$k$Ywy*Tc#wEE(ZEcUgtW>PoNbSmPgea z!>OBy)57%a@BD7o;Yr72j0WsT8-4g=%;>#u*wN;qB(#{6l?o~U@al$e?Ad$?x~^Ti zf8lOrVFi&~3l@e;q}m3f=T~j#OS4S-6>6JIbfq>_0j-e|xm29MoZim6(8#Xm<(`d)YO zA@8)TbX)k_C^>OlYG;jf5%fMe5dTo&Lp0-~5`{4*v9bGc37#hS$im%pYWg$-)%QwK z+%_{Jd=$MJ9}pNr<1Ra+nuA-L=-QLRsB~?;4dx8I{$72gTg$3HypuM19=#{p>=^_( z?`LYFJTzdN&mDn9s$83ht^H2;mqwYcC5-u?r`f$1e2C)`Q*vTq>&Ty@Ed9TU{a*1_)BK13 z>t5$T*-AkzBFRwZi~Q}PI2v~*nw@`XAbbbqK^n?n1AOKAbdd4R(#dFkNHH&!B{)B< zs7g#`H`Vj~xNgssYt0-T_vHh+=-$N$>|x^guYNq1`(2EhFEc+cx7dL+w}luj9Whg_ zDc?m=$4_W5izO2#JMrbw#bNV9aml>kzoBvCnRzYn>T%DShVJW%C+fnu)*+=D;sG;R z&?opoWls6+<{V5+7lyzrMlI%zgae%bzm3(KK8Q1nOX zS_<>pMG#UVSwSFJilHRa4f;>TiRXtp(ujhLyDwHX^&2shx$rNND=C>S^5}Rkx!j-A7Kn z4nd`cb(rZnuQksb?dqFl z7rJ&xb6;Zu1_&DqON^50b#teEMd2ng^Ov!dJn8V+ol(OOKv%PRP?SIzHmDn~K}(>c zJMW>sjJhf^?*D>~lQmlBUrNMSkpcxDffqL{&`p^KQhBF!Suan?E<(Jue0vPqgdjvu zkE~C?4%Ui}`9KwKWw`o|R+c9=52M!9A2I}dFVLdSw{$b#rvm=oLwL0#<@^;_A~QL^ zYUY9La=B4sHXURlgJQfl;3qo|$*(uXy5XDr zs~31|<}lEEstBL=vDDKQ(#hySbYM&FQ0niBGguA6nL?ww6m~O6$6)?QFLU*?N%Wi} z`1Z?Nu7!86Ba{>Xq8azhVS>ad89GVSWGI~HTQR?R{x^8i&Is@F>@Ssprs-fLg&fCy zFlXjQp`VSE9XHE-0_WY6c^Ac)|6!)Kt&nR@cj0|#^b9znRwf!$W-Ao#bR52N85@+w zrrtMqQbY`M`%#7HU(i-uYC8Kz=@s}^RxPgG`(soakqHQR{s(>a!0be&37g$|IioIu znvdW!+m0dxCZ5A(Tmy&wGH7SGCj8a?83Ja!`*ULx6Xd{*$#C0IpXe~%+PR%m5a~y# zfCqJ&@l6?Do|~&#!uHDSm>E)~FY67uoM?`X?yXZ0Z8$r|wMUpC^`liuZDDTh1fdd4 zFq6{OE9(KEW+zf43eGk~=$C%+JgvOd;Tq{ca`M8FZyy@He*#K_D)hDZdm!c4gMP#) z1^WICd;vS}T|TU9P*HrpRJ!E(^B*}0+uC{ygD{;y=$Z(z3fU-jT0J)nEz+ILGF>6n zcxWT9oXaULYHvgxdScv+<&o;qA5Yk;pYF`YwMUcAOQ4lMiF>^nlc;;X^)rTpueB<6 zY?Wa8x}Rk-9sdO4kG#$#MBKcDZv6IDd=X6!B~j1Dj}wWGq<3Yq6SoG@l_U~^&8*h zx{g~zo8^;Uyl~Gzx0Xp z7oNP$+7j4*(en*0)&@#Q@y6r3e1i-~3Mo;pF2F`zKt5wRLBJ8bA zynLC3-YzRUfdb3)_Nmi@sV7sY0bgghRGv`@PlBP}MWd79_jF$j`*!Yu(`@YbJjqgM zf3!m(kobqOtUm-Imgeo=+?%Qa1bmQGrx@Mp5G)DJx^@w*Q=sL z+D30k!#KGYzb|N?YQl2V=l8Ydo}e+RN_|Un>IdX+F#EV>)Q%OfZoaJsY%SN&!v-S0 z^!{;Og@F$3rGal~cp6s4rJw=dI9MM~yp{ja`kv71-($*w18Fwe6O7N`7Spy8U3Xpt z@);;OE}1ZdZwJ}uV2p^qevBXn9dTcPRH^9qP{Q8F$xAD$E{eHJI>oBvn|Y>5#d*v- zV%CK`>sKq_$Iz?z=GJ8;@{(V8Ee*LzzG-AT9-grEx&=@?N<~QHd`-e}=>O$>vu zwc7WNlC%KXeexlH$O(R^H|zwyKOG6tr8*ZQpZEmR&Sy*2Q`BmoPQ>7Wg9nB_fO)hr zaL8y`hm-dvs-Kk)XU{qd0SbSfBnRmVtVBKMUk_InlKQ>s8XDMTwGd4h2wQt$@7*n% zY3)yS)H!mnq)m;LeOw2=PI3@}_h%fxB#O<3*&#nwv@s?hIqQA6wnnr4q|xZ@3eJ^o zJvTNpZ5mLK8;-bWOOV>Dh$xP&BVIlP&QxCPF=@RlzYW#2skQu)co0`v{2twSigd13 z;E+#G$vJPSLn`l`qBPEr0#m?{3_^yy?^gtac%3Apt2V=4+RJ8t zi2cU3!wLl$ef<>niBo_!pXcfkpZN#=^iDMM|6pP|Nt^?5TO3jCStIhcZ!nYB`)u9|W@y4{F#V z&GHq1q)oqy2v%tmNc-ZqZGmC=r%-zBYx6?kjOHJA&9XCH- z4bj#mRd!$|9qjr%O~qH;Ax**r8)VVlQ@th^d>u^Tu4pNU)l=}KpSKs1Cp4W|&xv?@ zaW??z6j8Ft1|8CYa)T)Ubs&uP2SupZ2yubY?tvWEed#Q!w^FkReQVUg$o z_TiX#MQjyo2#4A?k;=Vc!KK9UmceTtcp0E_w`_@ri3a=5Xa8V}hk}P#(FhACV+BWUyS0*k4eXwtlPX$GEx4d zk?M*CWE?$2y3?>+JC{~Ob^_U1v|Td>7>|iy>p!szd&kO>!V)h{)N4JmNfzO z`P>|MaX4}SdAVK}B0M6^kvG9=>6ndg~V{djhG5Mg`ht)C@rTjJdm+#-j zi?ZrrijDddD=GI-thhH8J#oI02R(OFHroy6o0=xdP>bYI=0{_`l z1q_qA2_NZKWY+!y`1#-~c0YaV>3&Q_rp}Xf_8nC2-)Szd8C0U42$5qEiX2NRB zH_B~Y1TOvU(Jc6Za#(&=5<4L4+1*dLF$GHfNPA$2Go2PKm#^6L_Z~=b-2URn5dj2z z`y22`S^xBt+`lw2R<(b#x^h|6|4H4m-mYE4kaFE?Pw zIspxWdP&cx?XV|K^gE7g6H!EgO_G8Q@vB<~o%~)~ub=jlv+0T{N_E=!1zt^P;}h9u z;Vr;&6Tsr_DHLV*U_Qeump1E)#m2riu31 z8k|wZwx>~bz&P`)fH)(`UdJGv+(D3bh^o0)?Qh3Ee?_E)8Z}m~l-Vo`B`2RahK_}# z2Z66msqu1z4CJaW@eLhz4StrACpPzsNnBq}RAGF$$s!DWdc7Dck$$FT3rh1)5Lg;! zgB%MtwMQT>3or7Z&r7E0Zk-dnYoUgE8Oo-#%*kGx_iy@$%&Ez8ae>sK^3zDKZ6+Nt zvFrLNSi|`nhg=HxsG%X{RSM$LN_i$ zm;?3x)YPh4_;c?l3io&!-zngu=C6vQgVNZAQIE(_0aXuNL-dvXSwQJp6{)uhHk`bj zyh9UK(PxN0l2VMy?3BIp3QyS5g%lUi?erlpvkFGy1YQMcleHjYPfiu*f1kuT@2jm_ z#~lC9{gTwK{Jz8QGWYjS#>Z-C=YfH#UgY#>C|~w=I(5T3_NNPX%kerUJf#do+Bznh zg_G(l`zT>XEawa1vH!dgWvQ!QTlN%1byi4|kk2w66FR#F%n(?Zc1~3eQtG_kJCxk( zTS*QL$AkUakV2sQv1RGW3Sa;f&*cJsP<r^_bz~B}Z@$P?$I4*}|-P_??Ke$ML zN^q7(5jAEh`1+FD2sz6G#tct*D6afS^`;>PsU6%1b!3HX-9)q6`flnNYPckyELCSw zhI*gbul}#`Txy?LS53SjG1-n)1yJe}W;e^iPLJZ>82mQdFq|-_egDE~kuOPxUTo_7 zM$RQ>@gwfcX3sz=X;iF(%p@6o_hrWMALgQNvcQ#gp}yYMt$yoZGp`)=Jwk>KPeP7_ zdKon&_ov3}czv_NrOK?PH|R!a{TY}{O84s*iThX-jn?!?(nZ;F>sGn1#@%i`V0MTp zCnSP2izgJ!EW5~=g`oXr(?e0jz2KkqvzdB}!FYIfc>hBwPhNMLkn0%n@cWus_GVkA zCHLDs{jDp~Yr=$V#nV^lxF5rS232CUS9#S?i+d|{P(v$yl4mKgj-2jo-guC0@b=W4 z7!pxMer7f%v~C^*#c9jdkP{Pxen_(e|0&tRiu`VdpJ5{Z*t(%^^V)he2 zJiw@k?v7E_6S`M&B8sbxB`oXDy+rh`hv5|oJMITMQOjn-LrwnHcY4*6{Zv3rD%J7o zA5kBhFGxabGxBi$a#wDST_$Y!9@nJfx6yVmValVS^v9jemhbs}Kj9EqN8!ZrTb`x3 zT?`#2xWe7z9=iaxgsgc!JBwGGJd%DxbML_Fu9fvOGcDld#=_~2dh*^$7P<(;vfxI+ z_{?|*w;de+OA{u|F@@x-F$d?=xsvZQ(Qt?U~r`DGRtod^rx3uXl3VB0~g0&fiuOhVYcx zbP3CC%qZa~B7~+H5nYH;)o}jEW4y7K10(kNsEzML@p=#bZSQ|Ypqe#ie%{{xAwOJKp|mPFF`a2KmKuGFk-e}zwT>eb_es>M z+*%hj0cJ*J*E|(?hm>rr=ej9?_k4JN_6)6V*_{-j1qeTfD+qp~k=`yjpp$rcM<^$u z-vKmf;F*I~%WXEKfWb)daipw>s*OCxx7b4$pJ8UAYk|J2iK zs-bI8wDrcZ9|vFRq-RWMA>P1pjyp7vSG0jqsT6bnzxc!LqVKqr?L2#a=KlV1K0>tM z>FF~YSD<{k0xbCZgWJ_>p=Sp2j+k16a=pB01rhfVUZ+%&8`Wt_Ew&Q%HN9yKx;JRY z8AWLOE^)RL_;GtUTswm=hlmPIN&j6}QpBy>zpYzSF?*x22D5N$bhy%(&475iSf(X6 z{sXLrCmxw>zl2T&CuG$gMZ;=?jPy8r?>)=bS=QA_g=#Z<9*raixS1$yrcGr(TY@_u z!>pd`gRO)F>HMSsNPRVDI>DPitiuW(IlZGe-MLQj?dn7{c*|8`^H$l=fqtvO;B7_2h39>vZD znZUy9Odx_p6PIXtUfjI($X!X8(Ok4|Y->43f8nJG&HLZ4R#1JhcUDmzn@Y~xHao%1*2md7+2(}+|iQpIt8n#dk$1fPgmbz_%UWlNEKltBL zY!KIyEuf39rYOeB7M?yBH@_Q#isMS?hNmrhkQz?c?|^xE3W=2N}y)O&%k0<$A&dErg(#HF>CN)d+G&;+Td%*z|0 zfeOmA(c|l$)rL2aY_bqG3#u|nUFnWp^HcMG(yq>4EKgak6_1v%XGSxa{=eE6flF0x z8%7GbyAAd&2?kt&ea&k+sPvp4wCa|kGcqOwqp6(PRGgGL^$m zg!W3O4tl?{c{K$*wKmJ5i=4x~0o$*RHv28oNbXy0FufuhANveGDbmO}AQyvMt|W>} z&jjC3KFr?B(Hc%YsVL179+SVn5K@%SWFMxMr?jx4rW)w*gqGVcG<)3 zq*$Jq8u($;=~=|cT|xdWT!Li^4ogP7y1lepD|M{wH3mwsI3bgBXtyGMTK(62KD@L@(uqaCRRnFeoFj~a5ItJ=-os~%BvB+<* zZRAugFzaDW*af@G2t^L847?hG%?H`|LHz-(fwye>E@<%gHxz1MX7Z=E_ zC>jH^^7v0Jqjqwhj!+1G?+a|3MpE=NHMHq$`S*t(satSyGA7QIkgsh)Gf#&9!}YK= zi~2s6eT;o(lK;%+@DkQ+X$e}@UtA9cSw#EkMNRi3vK?NVSC6$KYYcJ4yYxULZh2s6 zVsATuMPtrXxh%;)GJI|Bmd|v2+`?sx2gn=ViH%r4)gYyslcQ}Tt6~3% zKs6^=p-<)0*^1^orasSWn{5)%4*Ag?%U{?v<&pO&=a-bxYvOD0BB<@#AGEH}l5Xaz z9P!dFCrRZ8t;0Qz!MCFRu9N$d#{wIK!;9*~@|cQ$M)K>zCbMPkV38fCa&GU7@09g+ zsX7=UVUq1BVT{wMGAf^JQkck%NY7jW-mA%4#_NU5=+5Jgagvn+)dGfAJawfpj`MHh zFxSG!!_f#=C%@?S1NgC)p)5BSpV`L)cacvI*C{4tzre+w(TC+nT0}x;cw^H~1S7H-At6Wv=~oHo~oo z>GHKsL1WFLduv`#?pO)=`;{k5a6!aEMMgaI6I32l{{*+TY=L-Uf`)?#Qzz^(>60&w zjq^z=AmsBkVq^FI-^-K+0~ML|Y}8$mra;JmZi3@=5*M3Yk)V{4@gAXC&_Nu+Ix~LvTI($F&(=+w6W?#W&M_ma-`>zM=8via8=b?9_u?ud? z9{>Ln5=7t1$D(p|^Yeb5|upZ&eD+>uJ`1WGAuAnYB zJ|WdxiKe<96?Et?_Yz^#c12y*uSY042w}}`5X|*|b9J6)xmbA#=%Po%Y=g!_(zde$ zDz3*e6b2BorvMSCW1OrAt{1ui4UqotPZGap-4Y* znHXDMLZ56}lBfW<-4cG4)lXZA9blK_YYN+rHK!Kjc}E0Y+##;S%i;-Dn)z^>L#x^^ z@V$ywZR3^yQF%TPQhBWO>F7xS6*vho(`uRJVVj%8?Gp8>wzpFPnH|=_vi9^~k#u=>xPE@`TJf1u?YkHG z3&-8cmqN$9u~uQ0{nGu#3iGVgJ?To-!fV74)x^KC%F4Cg$h=BYC`(|WRYyw`s-E#~ zbMZ{7M}b?ApD5iD=M;KQ932Pre6R--ity{s(!Nc(`cvC~KLcb|%Im$O1(I`CD=%_& zJ&os6=~~=+yB)_dFz1MvARZnEc$WQqnyT5C(u6UyOY#HS_INLN49|aX4s>3_#3qh* zlrYUfJ#T2m8ZwZAIu;o@453mw!B6DO z;tT4MF!IpR=f8@)|DjG-({v!z(_D@Y!a&042bUxa4uJ&3~TqJtcp6luN9!I+o9e;TS+=+!hDY9%B}37X|{q zqL7TV^eRzDs}SvkU9*=@*Q_Hd4~l10p9+yW;B#gu|937FbN)}JWWhZOJBgDiLC0JK zEjj=fG_lMr0=$FUk^lz$a@RSzM~-ao57~oshCC%&#Xyq97`79brl|`@ zC(=TT?$i0H|4O1}R15vE*)xMBu}GMV4(X{U+Zj#(yQ*e+(6g=b#IVeqOT)3#kmG$$ zM!)5$gl7PXtG^V&B4IFG*N&K({Thl*1_5u0>~u5br8BY`dN;K6-j_6GQ+N=>Pc)#u z7S>N@_4n0h73haBhU!!q1!np4i;K+3+ZDr_cN=E|&BS^0D&QV&j zwo18U&FC(`K$x*|g(n7Q?5}$sWs7-`?*i)`v`}U#c4u~B096I<3{$;y@bklgSJ(!k zYDN+>meSqj=5ywxh+7{GKeb9P|MEU|sC)&kpf`bAu40*fykY=#LZ5up41k%U36JvZ zXS^Gi)1X%2$v>d|uJ5E!`@B~>B0&OunwCA-rK-k?Q4-YpuIlX=;hB##0~FT0WIz9{ z&iSjXLZDra)Azq#9J=rynIEj^b{>I0qq)LZBO3nnNAy=#EnND>36C9rpgnm#23)x< zqW|gx)O0*z#D;?QS5Q3Xe1Q;$4ULP<1lcWW>EPagalFOyj<{ z&*MfD_K;zpK0Qe&lnu zDrFu`qpH0u>xL|G&BGWGuwp~;o2*2SlrhOC4gy}( zp9;(4bPQC(pvx&RKgDP#A-pTJ5dl%n$>b`k6K#!WriYwzEZ(~vj_Vj0rFVdW$6xB5 zH39rx+)5?H!W`722oC4T!tp7r5Z!zBC(S5;^EEYl`k>DNr}g3;i6DOtE&V9tRC*3p zV3gC%sR8;hPo(doI&W704if50>*L%2L30i!zZEKYlwVDw#(`FFT0i#_iE&xgKtdm_ zsa9%g3L#21*)r-l;)$0oS2hIQe*~)4AE;%X^9d!NfheQ6H1zS2UhK{5`yhn>waIFo zUVl)KSBXH{qD$4UrNE1r2N&&7$>T5tHlTThK|<-QLw}7`;8=;H$;#}8eaBPiNW$WN z@iutiCHr%bPuOOpolTFHgRs~YlR+oD)ie+ubzUdPicA?8Xt2G}C9*4XX|;OO z3Jc&CnW@8=P#I?ia_k`>G3Gx(mAPY&tfX#Jvz|i@<7X42{+=nIe<=|8wTyJ1N^3vw z&+ERbTyNlw&fZnC)SEC2sr57Vqy7@PVnwT}%+y`<$wFxxJp8ydapPKB@`EXDAe?@&Ev4SA^(sXSkfx$90c4zLmcLNnG4KP7LA(W*cALKn!p z;8q&z{cFtJIWghg=k~h}mye}RHTrJA9Y5Hu`jzEQY1QJd(W;@F->T99ebvaFKJ|CKaX`?C}QxeC-COtp4yQvOaU?6EgrW6mzPrU>&dqlHk>2jKb%? zd3Sp4C|FIyVVjDZ-_@t%P7jT98{8U+0yzhM(y-O;z)pO-cDYZ2J!|Nk7P~K7^4?8L>c^LyQtkXNae@i*YU$`B$05$N+v%?sqUNnnl6byTnvfyX$y(2LMi5 zy;KD`{gNSjn^XL?)7E2;R`n|IABv|l49~u!)FeQQ=5XcT(@WJf5@2=>_yh_gxLC%|;2YCMdUb1##Ig zli;lrqQdrh@cLPF33DZKTiBQ`OwUS%)Cv^yRJ|8iQ84u6X-9*7sGAE&xy?a2C3GsU zYCV>QM!!lx*CxA@Wz@lT@zK6Tq()WQQt&m8Mj(maKeS3LVS}CL!L=|-KQ-rN^|x;@n6x_S#cVfj*{;6%g$btgNkv$-l=d?VvSg z!xqwOd_cw+UxD(3cpSk)(lWvqKW5f1Y7DZGFgZFfhSd)eZg}ailQx57c`kABTIkb3 zIly}axZ$bzs~>slhLWN@toTDkhVYOF_lRrfecyVnq$9wM_&-50g)mzuD)Iq!VPer7 zSQHVZjiSI}`k&ri-z?(j=wvzJQC3XbyvlOp5?FalPkRdTuYs|&79s)MX{k8t-lj07 z82&trT0FRTCS7GO<1Q)Dd9g`Z3et@Vv0c~Dz7Mf<(eyw5+k4ASn1_87HCNe%ok$@J zaeNc6pVq65Y$E1cySqT#^gP3O2wC|>5=`r-igs%w1pS=c)@XAo7=-v8CCtaC`xw-2 zER82m4UG4GMDa*t9%QV;l+dI2sHy2>t|n#kNxE`z+A+SQg}P_caW&xHn;V|kJQQRPbQBgmC9 zpt@U(ApcWY)ABR+Po+ZZYD%(szS#xg#lTO9upE9L-FgXJQ6C8{#}o1+yx-2skviN} zolM%JmX1mzBOC{u&v)EC7qGIT8>a1jGNEx(#~5Ov z6(dDM@`DCXvTxhEG6Y0gpw2Km?S*3jO;*7G4r4b=IgnR}Iiom@w>%D9DFx3{T)OCn zW6GQ9mmpef9(6@OUT~gK@^r+lq9bwQl>l6W{@Wub$9*R!VF{$9$cAZD;%i~TM_@ry z+!)OI1;$(rS7KZcuu7(GjYftCRj05ui>3!Z|pB!*At_{jZQpQue~1Q zA7%}wB$l(35;ac}R!8-NnrCZR;3R%dLjjH4={)X zOLYiy;_sR4LJg|jG#4~GsNe06=LUX~3Aw|i>QB6GGn=5#kSAWH(Qw0@ET=$r_~vk` z+5H0Io#C7m^mxE|_V4}+k1Y~BB)F^ii@K&#i5v>F?^}OyEff6y)J20|^Qkyy*~-~} zI!16NhBhigRquP!VQBbmwFQh!ZLa|}b7dwx4(_M9sC1#g9!%S+C{IqN6Q)}j3-9$y z0A;cSW)~Y-&A03;k>sDBmZ}6dMaxCNV3oW>jdhkkLVwL>lrT;{s$g~fM$8C;jD?5A z_>dF-DU&QbhR7nj3HP15o2|o(%}d2A`=8d9{Q>k!{bH)_ND2a~I(7O;_-XnEu(^^b z`Z-WTE_&bk$R+#@02$!0j2-AC{*TIhf`~GKY(Cn5#Gq|< zP<55|l!W)x(ghx{K2mLuvSss=uwrBDnLk{{#?p-Yff8K?LtwIPsC&vGpEZ}BBO*pH zcxa&N+<~_>FJahNut%AfmHSp?*XYbA{xg4|5cnUoFrY{+$_V!QnQtIvt3Mbh)(+}8KXZKPzpNx_KIm3ba@lut>I$6jJOfjpyH z*YaBBDzdDd@HFnx6QT9J{FB=f0e<>Li1Z3l>4;kFas%(`YO1T?+|9W8uXY&QpnA2Z z$4Q#9&xBjI%ac1YEQ0*>ib2Up5|E33T?=^G)^`VqKW+T(y5b^bIP+{YcVWwnDx|#7w-=Sg67I+{i022VDP#4{(w`sS> zjM9`{7v}^Lf*9E8xTalf^NA|D>wRt>6@@2Gh8&YaPa(|n1Y5Ec;pcI5bZdP^GauB& zbfm%?R9)m1)4yD`c!shwFBcpMwBm?Pmv$uY}9bxVXf;BOI#N85I z$je>?v>{Km2^F`V)bcq#;DOH}kI@A7S&?6TIaQYh%%#MR%phFIotZa~4nWAj!5Kdv^|lY<9?!am8Z=v=>=z7`7t$zN;hU8=1QMr?)$7jwenkHJkLV|@W3>HlaKp8) zen=)8g`!-v=_h_-dv!MU_Sn-)^@UtI&yi`8%YfOwJ?*S@Il5GnROk_5`86Rty|C5N zGU(*Zr|a_n1W&7@w%v5I$OODv9u7-No`d>}#+*S5B0a4uci)GPI$m>4omZ{7V{EE= z_C_CA!yT0(r<(+$O(=4!;=ejAJBa?(pf=$*7`C=`7Os>Op}`q{V@hjv`ubz#N18Zr z%c)DalQg~w&h+dbX>GU7k5_KcM|#643^={Kopim!#r*-m#kqNPs} zB38MzrG*ZL-=wQTM`MaOZ&uHrG)3Y@-GaLQoR`fEk4l6t>h`}rg(Ols-;T>eCNKf7^Fe9ObB_`+f{B zFBm=MY@F{Yn*Wrk+zq9RR>^Ohv9eXBQ5>7jYbtIQYUn!b+}Cj9@_nvXUx__~haZsln!k1C4de`+$4QYJ>hVQf$VC+m~>MU}|2 zmLvCJn8R?_mo7lRJKpL(DYK$hc~Wo8))psuWG*3Z9GH>BB`&_0_^`B6H+R{Q>i`;k zoM611o(R@)={LLw_k;@Azck@aC{x)Sxi|MS01wW!K{13``RIs4nFbC}m3@A;L{a|7 ze7&#N4y!?csnoRKMBdaaWaD_q*z=Kz^E%>+@L}5vi;EkpL#En`)^&G>qhUv-P9oTS z73F-gDokr!-GO2e#Plk26nn}akJTFSj>*A|r<1{UD$&t|7$6oLj0cPvfkVy^|}r0c5q zWi4|ZBxs*Jv?)b96uq#RD6@L2Y!c8b(E0udj2qgBlQ~hSwHL*w5R&7CF@k+mPuO~T z>DpmiQy+Q+{o9eaShZ&7Bv_bdFMQiESB?@q@uytCN(U1rYt-@ zq~+8Sj+`h{7shRP+{4E3Yjc?iA3un2b5Y(kJQRu5gTEpqlfw|8M%{Xd%81NW9q)v| zQ(yY!1HU*_)k}euiq7+FU`F3L&ay4qRG`^-s`Iht^#Z!2(}KDVWP{RZYL`@co5`9N ze)U+z82$j)dN1VP|HO111poaXl_K!`4_||s@0SR~FNJbcJ`aJXb)6)HuPV)xsPgm77x{9Tn>`g48j?7@9u%+tS76 zjshr+_yK@a32#>Gea(LrRd4=B^-x9!4utTzj~*Aq@6G;?%F|_O4)RMt z;QqApE?t-9@4XK`bGO}ov|gfwmgiO-R5A&P&E*;>m%{PUlZQJtXIGx5(7ul*q73ZC zF>sl=6wq7zOORNa+J0CbXp3j0M})am^UErjmuJ8$EH41kUA@495lSiku9pU!ZDNNKfx}u)9tDscw3f!;{NSJBKxqi}8gr*_g(< z2STm|>yPg|+bl~JtqXi!Qc(&TWm4sAU@*uWwhw;tmbwCbcRYtdTOn$Y^_*460DtF; zYHpg+o%b#0289#c1k5TqI@rk5s?fl|tz(B2o$)qmS2qN|q*i$tb_35FrR#gsWoENuz$W!H`zp|3kSLJvh&Ju?ftqmgK3LxniWFG642iM3QtQXNX*AK$Cdnl*=}|E@MrKjhzkg- zSKS1hJ}$YTQAPKA!S12E`LRx;AzxkSF8T2Pg|E%>K1-d#riOZ7V|~nwVyY-VIJ<7? z`ma6~oxHrK%_6BeS)xApD`YUSpfjennf6p6M^zko6Qz)LpWWsjl@1_3m0eYh^(=)7 z$G74tva7d%@YwbcO)Fa^K^}{!b_3HLxgX6xQ?=68D86)EPJDjfGPA(+gSp&jr|>$G zk^CAfVhm)I=cg{big4=We`)xhlo?kL*eNUi*>LPpk;YywnGw)89wp_Dt_cR_8tgg@ zo9lo~8Yl_VZS;YF% zok_`F)7x~G`0EkOl&ffy#7la|!1cEAQmsVa0Id?Wp`MO7Cd=KtZ#{Jk42Bmk)f{0> zoXhHOH0eBcYaM~07C?mo`c{S57?njF1o=px`c|;zRM?|KsW>-@d1i%3r#k6p4hyr0 z?SBdF;QO&P4HlOvv%;S-mRCLhetf8*eK|j)xfGUkyX~|qt*XCm+-RNGt;h1?ZusqD z_MeCzd{Ix~k5daW1GsaeT_^f!*Z4n6x_(m&nl(OGn(Mm}`UhbUf#RF0U5;ioyWRC~ zq^9uak=$Ci?RL|QaHSt>=~Kfm(K5l~Wks@>7WGv*Z?r<7J$r}*#*X9)rq*izGS{5h zAH_yQangs)h8-V=#1>^LK^Xpob_c~(^dv16Q zrN#vpEsQs*2f6)&N`3@&@~Vqq`|Da#L#!zL@YRPJQdughe;5=k7M$`VDrFvpk(7=R zLUC&i#g_2c1+xC|T4i}yT(~-7yL{$0G9RVfw&(pW>=<97pcixLanfpI5GCPzU1c}(^XU~I}Er?oAiok{?Yg( zeSLVxEt%f((8c+uWrH)s-gzoaO9o=IjHy+tA2WR{_+8ch>w2OHx9X(B zaYVe@5jC8-E~66^=-ZZy^r+`I?ef>IQh^h1CPZx%{coJBhJ$WyT86Y9n+&u)b9ZxF zv<&1q9w_5P6%@+=Lc3f9edon08i@k6-F9KcbW`{20=b6E=gv#V7CfCg%L_UquaPX9 zbC$LqR7To_P9lWPe%LJn-x{Nrp0jGs{(c(WA;)}Jz;@tlO!J&)ogeErQ#$SJlri$y z4@|1zerE|sbHLH@-jA9>b|%1-%g;CKD#IVRv7M)~1@1NY-+hBcJlXXOVH{naYb&LR za(ShXW`{ZzE6v|9r?Ld48s(WmyrI4zpa7}ml15T-4uR-N;Dc1YmHD2e{yMmKP%ugT zky!iYO^A|Gp5qm7>#1nJy87&9T zUk)~AGBk!99g(YexuuE$%iyXG@X+iO4D{4_E-_iXWxBB|4jg|mxH8(Xp($zMq>`eR zwL7R{hjBzSz8w>n(OWxSvl3kQ1L_+D)mN{XK)fJ7t=d=VY3#M>Fg8%*VYl;=!yf06 zhsbq2Cg!2(#$&Ge#m^F-LH|*nh3s}(Y3InGwCXdre-KnSh*`*;Uzw=*-5wiS_HoX+ zvpdNjFNKem;&EiisKS=;SulL{X^laTM73SdvW4?~D1h7E0xca4xkwj!Y*_&6rRQ0$ zP!Ji^_RfYM5EzT2FDmD*Fqal)Z)N5^-{rwG`a6z}6(m9AKu-o~i1lnH?TcVZRN}lR zRcSu9gAgA5bo8x8UO1Ma%%+~diC8!$xEti*FFIya3?_B>*U2^?k zx8>XaTZl+10^T`#_B88<>E)$6_+0)UFA{+|??turuh72;6Fdx?yV5jsmsoq#mY}J# z9p|#pX>_wfZP=q*`Pxuf3~_U1BM{vnu#*tcWK%Hrup0IYE|)^UE!(Vz!ACOs?ccep z-{EsafSUU-3tFD?&sGty!S6PL@YFVrSK)?qJvPHr2&wa<2M4urF7=2?L1U*d8~e>6 zW`1|4#JS&BR)>F_X5fvWiq@9@Z%%QFT!WJNSL)HISHw%i_GDSgcxZ$1I^cJt+_^`0_+{vLKi_^2cw}H zH&6M?*0fp?t7V>0&4ROFe{w6nZr~C3-IR<}cn3{JKO5-G2w3aO75C`nV_@I7VVkCU z$RvDobFUY}Ajk_v21Vu^@8K?QR{4~MgBM@TyOLgXy~=BJuD#p{w>vWCr724Y8Q9RA zy=nc})?IHo-XYfTW660ngUjH%D)Eu;REj}mQ@|_7#r*df4iI+O+gf^q_xWK9CFhmA zc;8RPBb>#3s5pL9+c-?$>0PXs0M9LHj&;@8$^M&-QX|>x!Puu*A(pJW<1ihUx%dd< z!bRU`AH2M#EPKX!gF~IU=qf+{wDBNuk5Y%6k`L5lg^00sRB=n13lk{fd6jQDekU#t zBP+jRuRFHc-g~|pHIOfRHt6pJTkz)* z7L^*$Or_C{=Lq9p>q8Sz)US}Q&7Hd49%+hJa2>|?3FWt2#-&d(4Fn3nO3j<`n5{FJ zkSzRMY%4~z;^PXuc`aepF{<{ICA)8d+4}h{R6%Mz^*qgI(RoV(X$R$Of3hSwyH#qU z8S=4!G!SJHbG!1Qy|=4=YfYF751|RYVo)1|*fa^3%q*f>@>GgVWQT~Hbvv1Be$Owa z@B)xw?p-C`NMo-QqjCw63FCpnO5#DQ(;K(QhJd?4DlOi`GV#jho?pg_D7a2P)3X98c4_I{`Uf|L%*uUC1%Z$H}rfW8YclR`G$CF z3K7yjvM;d7R8jD%i>M?I=Pvng+tZTu)UmIIkaXKP)SHf4U3CcPH-c8;7yHgbr=_w| zVJl*nKo7Sv%7)!9ApVca2@9bM4Ouq5#v|&sUtVSB>?Ggx&i(%6_{7@RNg)+7*TE*d zzTYwXou!jS%#na-*szc9{Lvtc((`I4O|Z^_LcqQn;PyJ7Z@=cnUY*qWzHlTw%FMgg ztN=u_C>#rCbRVCSK;lq0P{sM%(jQcN#xVuA=)t15nJU%1y`e6tD5S@z`abSHbJ)0m#&!}6eWA4+PuIDf5{cph4Br+z^xj}A+UMwFcrHb z_umW51z9nZ5dk#W=*u_DE03Z%LA)t=ApC5sgqI6_P1F z^Y-Y^^MAB1{#weu!y<}}6Sk8Ey2J&?7iV8oNA(BXHm*Kv_Y_xq0gOrU;JMve=Rp}W z{Qh|DS<#}aLE(Arr^p|R6jR@g0e~LDEtBsv4mtznz$f-lAOKq~=Tdzln7C_iZ zi@I-H#2hgv=esK^XaZ_q3em4Mtm#aAjXrH7HR%{$wz%qjzE9!P4DkxSy6e~J8}O#? zlbynG3wqh;vJE}U@E}y6&b)E{;S#h zEdIGBA6%O}a5ieN%m%5waJ&_iVRksXJB=NYv^a8GOND9%)pZ;sSh1yWxoKt{8e+nk zix^o2nyzGcjgb;nmu4$QI}YsizgE(uw9WgA985h$`luj4#;Ug~8Jii`@poq57a?rw zueP`Is>#-rFiZcWC6>#&CY73ka|quH>}h9PYV;kA^_$Z4o1*|lDB zwgJ=4^jthBSCtGZ71re!Z6h*DF3-T2J0}Io3TFs9Erkf{#+G2pgQ5A9NJo%#X!5@b8}wfs zXioN*Q?b2;*@=OSxE{%9w=YaBAz1RIG{kNdoidlFTO1tXvm<$EOyp-)?>Nw?uh>V_ z+@*^=e)-*SY7tbb&=p)DVSc#I*#2e8U|Y1Ih<`t??S<*?ETA{eWk8XId?wA} z-paGSrD9Wb>C}_s+5gzhnLJ){?O4(1Gqly|@vjOtHKn?qR+>-UfuYJ3a2k@%C3g8# zZGBcX8(j`|X{sak$O620Diwe*UUzoo-%W=hsr+?P~SM z(&*QcE7z&(Dv0i?{nE6td(dgIa;K4N*~%+V zWMN@m4I8X|DosRIBqK}H0}-6Pk{dLkAH<`sFtvT037$MJr}D=;@5QudL#*Z=9gZn= zT2{|U7;lGKqxt)Bd8T^prUCB7yf;kZeQmGAGDeC>xT3^Y6aq#dZ*wHP!# zsFqDss-rKpHn&ggvs>?c4HkbeZT?5n?EOjocZayvAIPz;e>6^&jZ`cQEstEJPjzm) zKY%*+%^yi~DJ9nFSAC2tK20z)wO;K46rsL{I*JBA9a+{R<7X4G6j ztf<1hj`wM*kZ}N1i!O-!wb4q?t8R>+B(q>EcT5EW(OJ@X55r%JpAmw{+DH!CSdnA5YeSIr)=rELyX z(+XJ%!bUWlfOu-zp_V}~JkDNK5dBi#X9ky4L7lGRByxgb@gJ@yYlPHNB=b04(W1J# znSBf#RJu#OrcgJJc|{Wc`mcW>{Q_292vF+bRlG-FjB?vjB(V7SwLAm(%7L=7(d}1f zdE_9xL#jvIK+B$eI86{<;=XS$G33Su8->c|xgpdvH!xisJBUJ3WsuchYLVfc>ie~X8u;J_iE z(*LMThh8X`UxlOQbZsG^mw_c9j5O|JS{hZp%&n*RkXIWmoJCh~2>Bj^B(3<#@aX;WiGumzIzK(b40*?sQPJSY zxk>z6+I6G2a@zMNr@gV$-?iJ0e~7_1K})6sF$J`GI3dC_hc0~Iw`;8j?ytl~m}%HE z^5;`%QJo)ZNg?8QEJh&iD7GPiVqd4)SR%(_W_sB2L8;lN(go(rQA(Ktu57@aT~G$@ zcoN`wT%3MaDz`mh3CY^|;8B$l-Bw{wtv$!Ff%h%!HzWKOp{Q_<-lcSnyAd0c-!|Oi zcHTRA@%x9cZrZC*wP;zR=vS%34w@?W4FiY{h8>R%7QMd-cV3l@SRGk(=Y`y5=e@IL zAf(ifxrNfz&4i(6x2qK-^X>yj0S$9w)-;83>6QDT1s=!XXT@DzFb-h-YMsQlUIx*S z3W=iL(5CvIisZ8C{wEb|_GM6Qt47=5VuiAp*7`&KVz5L!2}4A-N(lt8lF-k)0D^2(>R97g}BFv>ja+Kxyx#ghO7-^0E!~8 zK5ZIVJam-xGpv2#E(vkp=!|l;`*WwxPj&%K&`S;!is=OTJ#D?9;|0+7Cxj<2IDepc zOzV$uJo1dcdXd)^!#i}f74;_AS!-yvFKB&rw%YdQ1I*^+4phRE$l@ChbxI`At^4NC za#01dQiP>q9tKA1I^;jkKiBG%N7j`p^l51ITUoXkKN!-ARtQg$lfXPxIR5DMv5>QF zndLEF&#Z$z)U4BsY_0fysq$`aWlAY$-L1(=X9?eY>Q)mw%RTy%R1T~wxUA#RuX|bV zKaVM{!f91nD~)N|h49opwSmuN${tv`2X<5{$`dC~vqA%!AtV z-z64L8%1}s!DQK=dnq6-?SYRZLF($mRa^h@bJI8%G?)`qLX6K)&(W2*BE3@K<6jPJ z6`sYtLT$AGLM;MI>=DW<};~le+Sp8gKdhPhRM@3vQp(b_~O?6||+a6POe!P@u;6fWvI+NFU4a+RpF8St3 z@Ao2;UZ~rzuFoN{pmyXNq&@LXxjn#X@p>NTZpCuhcsqKyzBmhf-$j!_DcXbch#-k^ z7#M2WgeX?^*WYB4(g-!ROi$ZC>i#43`eE61Z@?n7Q|t8jNdNcC4~>IT3K15_VT0LG zu88Q}56(+lhr;pe6Ank(!vB?1?n7JA|3`s+HnO2O3>#O9)@qB|6ty==5UWN}d&G)8 zW5kZVPD@dHkA&D_#*SG^ZIak&DLN2A=`ea|d;ZV;e2DAC@4B7vrc8>=exgr77$um5 zj{^!|ypAWPA>h^7q&F@n1nw5DXM_v+SK}_O(iKg+i5ac=UZwr8S+#M`A1IE$;>Ni` z6USf8sW^=HOW>BVmBUjnHMm&5rT*YjZ_^i@`Y&3Ige&!)H?f~ZFvZ&?!RSHyHd8P&}y8X!?$EQ!`&VXNiaD!#Pz@4@AV#CF{I6 z&VJaKJ1}AVvWl~8hMG>C(SFTSvh5Se0;T3hq464!-h=#dEhva`p5A!1`zioZ;N+~| z>w*j`c5En0D-G^@%H^YHlF5 z(qE&j`^6#v9y-}@i9?eYGrkCaM5AkAX;aYA*P|WZ@cRcXOm#spCAlR7%vclDSRwQd zdQhRk=$iDLtYon`;w73R4v@GqKZuo0YU>r-a4oijFs}2urq25F4RiTIc|JcXDpnk{ z8Pipe_xE-PoZGCao80fEA3$WNt$J2NH7y9RC7OYhaLGsmUqMMfa58eop=seq<)IVB zq$=p@-CD4GYriNn1SZ3f=JFC(j@;-@8j@M=wx$tehFUv67ll<=TPO{3Y^-QOUXcc- zyduCJ=m7DlnLc9Y@^wxlSi*4IF=;RmLv5&+1QixcLT#6==)Z+BS$KVZg^B*9@NCTu0nxo;HBcQV9@+?x`sAS);@1- z_fSwuvV^`LcgKcwZk;h0lLxCo1SmaHH0g(lhZu0rJeB(xS&+gU-sZtmBznuksa7;Q zAJoFDhL%XD)ek&lR|$lxs@<|B)M%KjvlDzk^JTN5aGB%C>PoahLX%7jAxEX_z!o zfu65%5B?l1RvDwBb{kINQ6lSq)*1V2#o`cVZJ?a%rtFW9=OiY;b!3L-HMI3;6KyY}^5X zFB1hV4Rj8jz_q%7@h_PVBVZn$2_GDZ-j<%$0ilXmTZDS+xZ(`^3{v6#=7fp8D%0vI zFO@>=ePq-L+heY~tqpNJnEhsNiW$)i^*|JLSO^4||FC(SB?_k38>2&( z8tBJq)#K`sa(66uY$ERyE;7&z5#NO-Go6ynG{ajz?e>*=A{ARJdjO?5lvv1Oi5_J2 zw7)myP+ER%hEccm^V zc&fktF*3_#RPlTS_cfZEZN3$BdDE_RW3D2{!5M)0K$W5y6`wO{=ZAW(sTDE>z|{MAsdN> z5c!LZoL&0$ujvEx`Az0bu#S!{#ZRltG$vw-_&yarng0K55jRq*|{a9o-GT+gfz80ewydm=1 zWyU8M+lIJ5Af%Ppl}XM=)oIW1nfJW~tm&v%o`(fH3i6v)J1y(g2_ZVU*4}0hs?yro zG4wuCmRGTWIvT%SEwW13@+)nx+;S18BlPgO&@i|=h^}VfsAGh>ODH+<;L9DOm&AJk zxn^RH>jY3))1j+VcJl=jQ(0tEUc2chT2`A4r0~$Y_3fpN1BS-^bS3BSkeoc(<>Yty z;2i(97*D81xJmJ1&(>3OYaG6K&T>BM&-jI+3DR0{df}x&YP_)WaqP=nprG;eLMOEk(&Rv>x#qQPzCj zQ0tb>l}K(Cq2z!jCuaM zWso?qYK?oH;M;JiSF~BIc8r@$DKa&Uw~v*K@GtEUg~uwG6m#SOYc3Sc^4Pv`1k4%a z+$Gc50Y$7g(bM$ocaci+pbe&Jw13!@|Ms7~`j(48eH7Jq>&k_ZqVv8CGgS+sXIT5O zyE5MDveskt{)C*Dzex*ANXrfaYFDaCN`dj3lQFqcUOY&NUK)^cdw?wAB3^>Xl3gS% zQ(>0{QG%JBeJw#9Wt8Na0oqOcGW+4EC4E3sWN{w9L<(3`s86mCV00x+H zY!2L3t@A|b93w-RmWUb(&xyp;InVdnIhSigZa zC^0QP%%=na@WhjwwZBY}1*%I`KYw0#mdzqR{70b4;gorDyvDnR?q?UK0aKa)P9*m& z$x7eSwwp-9wJ@pcB~h^kwd!vVv%3@BRqcPUZl32vik5RCY{VGb^@9h678w+VLiSM2OeGz?la7TMT9>6Y|(yY z>e))Yu~f6-HJHbM1Pynq-!IM7q3fL)eG$H3+`v?%h z_+f4&z!8br=<_@16SMFP66JbOA?%Y>1P!*}p<{Z0wPHuy4j)98Gsuw&(ynuCgH z_Ja0{8*U{k(ZVg~bTl6x$Ii26pssv-9-R0z(78zr~~#)MnT&iy<0t zm0ZLoZf~sZU|dhuM_GK1P6aqw@58V0X>W z&UK;rq%vr_DGeOfBiB1&<$P3IQScbV3CvM%Upx#6gc$&zNk{Z<${;J))dfK&R_Bh) zfLfFL#I5x&>ArQni9X0PHGVi!|rqZXW@@2Kh$`Q6KfF9`qlV$5$GrGm*C>m56iJ6KN&%h zjK~tHwx69{(H!$=<3t(;HaoPO*ZsZQds{>J?-cTv049xqcMY41MLUH>Q=^#`@#B=4|GX<{~I>m7AW+>3Xy~fX3@f3RfqT;D??-y|{t5H8(a$0$(nC?T# z^UbQRSC!Zgcv~C~O@xSFRe-_UMn+cD(Rs9+BY6g40lvNN@@*JOLBJDd4 zNz`t>`b{|zA2RlL@0;=W+K^lDM1+`*#4e$ThnN)Uz|H{D6|KkT?#TBjvti4p?-ZoQ zJ{#_z*4kR-U#|qi74_sDG}aEJd-R$_)s?Tmu-veYnG~`co%>3CwAKhu=Ucvrkj=TM zPX&9Ag7Evp4yO&Fcux3VQO)OLz#&~ONi+kKmKh^uVoparppN@pT3|&9Gpr><(QML7 zd)RuRd~$0lD8df@)W7c0lMKV4V=g-}|w9xztK z>9p^2ziE)@=_tyC0p0h(rEf8Lc)qQlN=$QfGIwdgXwzFYf3=iJz|mA7I#i)u?f zPV$Bzmerqk6^XdzN)$mEEq*8lk04hJG(|p(R>Xb`080*tz~=Ue5dyKl0S(Bqa!eX2&h*<#XeYzmI zg}4`dI|8Eoq+2@E=MV3-_9Gfwqr+^;Tp+j-EPE+()UcPzyy53Y;Do)c#&jmNSAVbI zgNHny?}p#3k;+7T%%5h|h*Ae|CQqu%mj=NtGtWirqJ|e@El{qFutIkSVtLC8#>%}o z9g8r{L#;r_0QFs2<#17;nGYj|paj%t5_< ziQr|-Dj6`fJxPx}#uKWO3jtnnAMbK!gsId}izcC@EI{yNWLdwjb*TRK+^Ki4(Jdyr z6`9>F(=8N!`pPdo{j&0H=A;l1sG2;yqTo+Gn19o?w@JFJe90xCdsf7S|M03gL;HQ# z_p#RNf_nvf@rC90>$gCy=_<Q)iv~Le6;I&;ii_ zeu3FVd;(U_sIPu;bit65;kHHK+~A7{c_Vq{M|=q(^9NOC{-Z8_Gbft3Y}ztz^uhkG z`Zn~oB?6&PL34j(LvHJzmDayh4r2+1=i$|RM4;9eSLgpyfBm)lZDl5zja!}gL4L$! zeG!xd!9?mTR`9E!yc}m>een9BKJ|ciM%`FfjOZ7}#{n54h*nR)@R(AEm&!jT+d=L@ zEonHJ@f>DWZP?1XR*PgzTnS^wgz-PoVYNdK33OWkwlJ_OD99+kb)4{0iHX!EIJp*z zfu#}(d+juv0r$b)p>`LOZ=vlFwOnr5Q|PO~t>lK+?<75mWg@aECD6JcF$n=v-rJFP zSXiRglZ{4vU<59!hcX;4o7|jat#7toM(uZ-Ni`@6TtkUVab?&VV%jGJPwt6vUp^9h zC&JPO;k!ffdOV;ZKz3??LT3&)z@;mdWU;=Z!pNiLUMcR~XAlDF9W@`73ZOr8?nJrP zPoHLfv7W4;31hPAO=OEGu({pak}gwGWVc0v7KVLjT52GwDV7)B%xDh)ENfCWa-r5^ z>WMNYx}H(rmT>aL75F;YIY-)96`3>DD~}rrxcsnHD~0zp-Vi--WV1smma{G)?9}=w z#H$6xR8TXiK2(zyw)giA|7MEIaN(M=;rKf8rs*;n`rdnPZerqg9x}f?=D<*I^q;V^i*x}Nh^?z3PH(3q@zx})E|>z>?( zDxafEuF@|hQf`MSF|6_{C!E2XK=f!(`v!LrU57qsx$bej;}}=@TceSGiE$a^rQFAV zfkCD`0axWmclhlHT0NmQ7+*z@xgPF|KRO+yHqx zkdo$b*j)k5uHGaI!s7p58nAEmB(KtnGZvSe+XHI3(f4GuW4VsqN-lY=2kPs0E_W}iX=?osnJMpZ$W3;Wl?~6DStBntS>n;VJ%w$imb;dz+5OYDIv6iwtc9G#_W&W3!5z zUE1?!&PSMN=hbYzEN=h0(vZ=jsA~03T@7$9ixN9`ZWp&tj9YgN z5(HsUxrfpxCfNn0UCA9nuea2C9Z3|(zGdR3dYz1|0H9XXf`Z-(QE!Yvuai(&=)$o&k024JACS3)kxB>1;?%ng^w!?*(w;lX z+7iG7z4v#J8=7VeML)1`wbHRhZjK@I;J7xCKN8<`y|7RB_anMV-=Hj! z>Xj5y`Wgi&*HaawR(cQUIEkfE+nMTBC7Bwz#j(^YE8QpCfB^ZEcQbNPJ99F6cO7-~ z8Qet!?xA@t=fJ!g52`?2G&IRC0w>N%f1)e2Cnr=g{&Zhx-iU>$-4Ks1eulcKg+Qq) z%L&2n)bs%l2yZo8@2axc{NOqYOJmCF>ePHPY`LSrXQvWNJx!HpetUr4`;&3BMcNNU z%BRC@((o-J$H@*Kfq44}z_Stmnyg2BT{pNLr&#jQ%^)7`pUheI;E%@aD}fk!lcKZ# zK6dBa4gUxoYT=W|C;TUJqN0M`Jwzoi-$E2ongT(}wsG5YxNnIq`bD$aT!xsX=k1oHfu%toM} zmu=?!-hGUxb(wW?GfelG^t9Juy#i&DkOeEV_EiNDnn-cC1vS==`PLiP#}=o!8y=)S zWx5q|>LjH?rP2E^gSs_OW@@u`l5R1I+L;Z@lh6qy+K#2;^jKEIKJVm8r^K}fSS&s- zLF+u^PErcqto0VWYH#=3TI|(y&dK7Vjv^sc>Rv`4{3pV-iA_@Op{^Yv|`28U@!sfa?2qAGtfT1YX@TQwB z22>O7Rtd-2S8=@`S&_?n{afwELU&2~yqaNa1*|}MQsv%Ir zfS9+c%!NcVDiY8<1g-NHu`E8E%!X}(K0%4kmE|ndO%!0(qGvlwvcrv2C)2=d_UC#0 zR3Fv-BeZ% z4mYmkE}ym_%e5|&@}9w3Z$w@EW9pm99ohIlZ}=rEPjty;(e&@5WNybWc>xSF=C1mf z-acoJ>epyGmw~ zNG2m@`1Q+;a3AAP_ThU-c}LawN~KSMn~r0S+zX53bbz+w!`-a#zSrGgH+HZ};a_sX z=hPzXElXi`W5$|atQ8j>T|V!x#EIV^L741k<X@_lge30NYQ~x5Rt=?SD9ZKiTWN~=7X;InI1|N`E-6UMqZ@AdL`x77rLOTwA)Y5>&cwH?5fps; zp?;OqHgNK8rqjM5aJWIhfaTuYXzPn2pZm2PMksWL0|s|aKO1WtHqTz6>AKr3o>za8 zREDviGXOc@g`PmuRVpPfwD39y+n}K7>bj30tVc}6lp+G{4V#f`qcy#IS2w!cVujQn!nM*9xet5~H zFA#16&0JKMc_FYaX<`WS9Y5!z637|W=yt|i$Voev7qz~p5u}d}?xG{*kaRvrku{pR zG`J!~`(|D+_&yMAanIpra(}RrV{?AX1lB@dw^MTn&4xmk_}#!I6+ry?m#yKhQ^?4= zDf~zy5ZT&rTc+((aDk7A$wL1ZhPTV*p+C4{K%|wqgUOde9hT!d)9rCKcN>|Z*EOZ( z{k@Ihu!7n`=2b(OxisX9y*L09XH3n00OsaD;(q(jg0~-va9~ZRQiAhK6I56= z-Yy#GG3u$MqHeyKJJa#n;8wVvB2!Ssmyx&dpHye6p11BBz5&fXkvs>}R6rn)*~#BL++$zui#9b&NLYGen9u&2 zNZ_7#XBx5|;O}B9)%c)P*y9!^CP8}lI$t_{B0ZoD0KlmOUzopFXdAVV%!5mN89eQ^ zFC~_q*;&2U*z6Y~<}TGxnnIX7fuZ+*tb_+dI`eM0DTvWL46Gz28+B8=7k_+idTy!I zRu&rF-fhkpFvzKp?4ze5NeG=&4^{RH_LiDpU!F5h?MB#H>EOS-Uff2A4?ufeNXE_b zHlY^;u#Wb+Y}HJz&@j>aW@UscwbZ9g_BJr96sjEd*lD+KeTnuUcp6js$cH)Py%o~L z_BT}_reN4ssvg;Le55L8NNhe4;$p$#8-oeij5);sDPO_i>m6v@&xA*jTOZ2licYmv zU$1(0h4D?0<%V@6dWvQqfDKmkHi;j2o(wB!l>TMpj|lz6CCLMBm3g}`A#ZSNzD`|l zA-C~mufnoO2KLIyVM)4?DWBA1NWwTESZ5YWKQS*bsjS8buX=ZnH|#%LOHm+R)Tb6ZZ{7OJMzFR=hh-N+YA}`ucpaR@EU5e zgddGKgzlJkDxEF-V6#UAMx?(d{dF5Ku(nGD`WlZqxjz-42X>Uyrp)Q-?$TzilqwbJD)kCj2wHE0I;6CkA5SbpcToOc`>`$k*$( ziOyhT;m#b(qTF$jD35-2!2+ibUQMx58Vkw?x#PtAUUWzY0t`&dK;(L2p=gLDH4n9u)8 z!n$nNwwn{{9KR-aaazX~9cpDY-Y`$8z|M1SANhV^PiYV3A}wSV;AMxM5g?X)a%&15YPRC7zjMGuRciBGBy`L9t% zQAM*-UQ%At;R^x@^x3{|YzKd?{ge3XH_FJlc-U2F%W=LcVd^L1#AQ9c3wlp({HIv< z#crFU-Dy(RT2niPX(bCbKXnzv(z9gz$#hz~CpX&5JR_Z_)3RHPMSzcvwFy>=XOE0@ z=22ut@NRH;e_ajm6YBu5AZ%`B0&~SuY9BtB#1zR2m-h$jc6ZUlV^a8$+B`@-s`*ho z`FMc`*Hc)|O8oL;VQaqZD86MP)o600v)3LV;$P3$77uzgN(A68I)!T{(wD*YT^^pU zt^claRn!L^-Fc%I?$KxKLM=eN3%sv0pL)w`{%(lrv%&b<`f%ys{lJ}}qK78()?UCmHumILkM*d)#Q8hx(68S-G9UZqa6sqGE4HPVzpuFc)z;gg73yUAX24v&oE_;5hw^WJ zCbUO0emC|(y`P;it@np0->vS(8NUm^P6Zk|x$IX+=M(}Q%9OdosN#*E+txl*G;BXs z9Qj%{-M#T^w5LWlLu5j3r>F;EoG~Arf}c$z~$TF53PS*L5G0g)-1t8$evV0;!@kwq3-rs|5Qg;C3SZMi}Xb< z&jy_!txvqQoqU?IAXA#^C@GSGs)n2{-n^B~RbuJCY>jJXTB&I}NJwam^+^4B<+4r` zsDs-jj?l}9=iER0(N*TN($VkBl~;ylL2FffTpM1177ckuS1bK-xFlWDFQiv#ef$OKsU1fOjRWwp2dO3X8* za#Ba@=IMfA-L;+>^NLbyNTz3TX(AU$Ls8^`A=cUk>Cd&4_qlYJIRZK62 z{gFytayCcm$%Xl%eGUv~&`%3j@=`D}wtMWvO#1#bovxZ}W_~p(r3kt55shiblC(VVLQUMI$BaG%>kU%()e1#)p?t?7KQ3dR@|&d%t&}6E1tmTk(?D zUXn-zC^>Ab(X{wts^5u-r*f-1>LI&0E;4jHNK;NK!(0XY8$WS4aUN`V66mxV9 z>6ONOSVRarMAy7{sn1zQmzu{6d*li5c2013-v#m9-yAktS8nj{Was{b8)kRIczPv( z%l~V5zdSn14xdH7@9x<6&_fOn!a&JQ4SL2~CN7Uw{|)t)|C!jFKkMKuoe1s$vZXdH4Z z)klm34|oTDabueJ?qTsn?B*MHSXgDE8|gAy?+lEESszpTm`nVZ1Y3K1&D(Gm#kcQF zjN_X_eQ=@OcyqKN`|hb?ers&==QYa6Sc-#?TyTOH^Re?zNyeOVhtP{rHTjI9;Xds( z8RGPh9DB-FF^ide0Xof|&6=Wgm4KdH={ok^lUTW^VxAdiTV1x)betWYyFh0dW2w|^S=KGg=*Zmzv^4+;l4so9l-&vR4OBhm7RV%#z% za20;nOy2It{Sgh2qIBH#&4c8OO*NO@=&Z(_a;sV-8q^j5lg5UC?T*tBqvBFoKd)C; zZ{N7MVals(W@)je&rH-d0hPYyj#Y-;ECJ{?Ka2_T`F_vhUOoc!K4=!#l2G##0e3mb z0R}8HWmjsnm{uON`PycF zEO=+9k9 zrzLOU<`rfAiQ@L}e$lZ=hb$#evoE?(6K3GQ?-ntdyl-hvbSA62H+~;)-dKPbDu@Pi z_HaVL?CuXf7a(}LyPrXtaHV8xl!Vv*Qu!yieciPc#YCPhW;S^2+gj1l#y0V4O(#Q~ z@Dp59?~^EhY_Xu-@WJ4Hh4hD1_Jz_^o0%5A*-NPQT;jtKvQkf5`G`M09{8p3zUvrb zcHtl741y(MS+VT*5z7N2YWKpWcoy_8|F`})w*8|IY=>wQr+WHJv9Vb{*uYEj%@A9G!C(RZ)#Iu7neR7EiOH7pz^({S+&RVxp3ZPt#zY%>B_CBj7c zF+{Vvp7vY`eQb+xw4T1m_yWW6Lg;4p(MYwQOslVI_cm?Ix#P!&Yh~g9_V1L(#X|g6 zogh@g+B^GLq`kf5Q~V>mArwh=(QGGxreT(e9|n`50yH| z;lZ!_bW*QB+gcxVrX)qa)#|HiFg??$98MIdhA33E=oh$0)uO4WYWK8XAQ-BblYjI_ zW4V|L!NTX0vT$<>3!=y-PJaRIyLzF*rRY!l7N23u2I<^(^`0+3g9Xu!YDGH=TXsh# zmUeS&=rqceS|!gH#=J0|ABx+}7M(!*c$x9|WLhRYxaGfLXD{+8O*U~Wj=w6Kk(rI= z_`BdZyXkgwE2Ya{@8$MzRIZ08VvgK+zBI&h(pi7uwyaJL*0~>$#Jv$)6d^>I8J0_# z$g#Tw`FQo%f)F#WWF*FrYD;{pa>2`@g%0EMXqy9kycHh_*n%`5qx4Enyyd6E8Ra&g zLvh3R=b(5Cncvk>|CJ%A(sIuB;o!WHb3PzbZ@A3X4u_hV%=Xklce8|(3aGa$$c#k2 zy{8^93$n_OT>qn%3nGI@^9`$Mu_TW#4l+JXL}CkUI=wme4TU5P7(bK%O}r;1MGh53;tkwn`~ zKYSt`B6C^M%O)*1gWxcPYB4rx{dYXr5X(&qgdAe_+0VptO-v(MSF2!q*ocaj7njVl zX~qeNgX_N+B}3DKD70;=^)a&kd!2Dlbg8I3Q+UR8{7}nTv zrU0`q_%%(zNzUQ1-f&f?D48cpnXixq_g3Ys*JAAO2dh!ySX_4Pibp{fki>dvqZonu zjD9wN;?U-hHF zaPM|0-bl9CxnJ(*tM82u=*vmpmLqK`S;!%$_0u}Mt{YDp2n45><0R%tUeY=dtG92x z2WPSu5%*u#iS9iC?JXn)dOfzhL?7BDI!0rPh@1zi2;Pt(jZXw$_ONWPQL6K?l+D$$ zUN_K}&noj7|2fQ>{p3FO8XJ_KRQ~(dFHRm1RzC9!u}btrcK<2QIy_v6?nbWzLi5p!{OTPKI>R;w_U%Z3tYAZL%FU56Hw7aIt*@vb=UZl)A=w=_46 zRO-JtJ{1e!(AZdxBc+ z0FHDJoM6DDtZuE|F|NF%@4@UG<=JD ze!m3E?oo`0AE9_2aCgx4e3X%m=s0dwn6;g<482~27Cnx&8Zy{!yPiYQWxa$rr&*`y z;?k6qB|caVN@~S@eMcq0CuxkSTi#fVi95O=D?X~)?VA%W_KN)w}$o4_bbICY6D!;9=JCAIeJjRF(K zmA2tcZB8v$zB_dEC^ZXi&v(kw;JX1z5naI0jXsgfT$&Oy#>!eO*vJy9aADNI;kY$WSiD^!t2%y&w~Ehm_;uw;Z-g%oO=;{`jomJ8qD9kHH2M0^|ETg%+pK>Qns4G@&C&1rKl73i zH+i_7F_dt$?cy`=#%nk9`4@67guhJMjR9LrfHK?Q!o9gf~KUSTQiTS)t3 z@DOhYU}ll0r5vfu$J{?Zx^j>Og z4>R^iZ-kG%_iTF!nxb$R-mxT`d%#O6Ca?;&(QqJ*`di$m<-o6yu+as6ff@_n7+WU? zAf?OytFDdaHP|cyj-#}UhduQk1euguU$|K%g*0wf4W%zZhK&Di0li(_gkw97E$fbJ zGpz{=&$E*SSh=XABJQ3iAkN>Y^Y#|=>Bo5g1??UGSLXA+Vpf>Eu{)!p0JDt+4M{J~ z>~u3yxEr8m{yzV-$$ zqPga^K)I=5>P?%8{C`zUp72&@=+(Z>rO?ry-?GbSRe&N@HQQ=RR+=-)ciYy5Okcrr zOwxc%B*7G?HKp5#2#n%G_1DGdoO?EV(Da>cHU(i7NUyK2==S$9f1!lQ;NNWaW`X3g zU>~F2!dIu_#a~gI!BM%3KJg8cPUfIAQQvs2vRDg16oHuK{fD^;L@O2Z$mSD$WU0tF zv?FB*ZVUA#7XfN-3|{bPiVCH8QP1XBK18a7SFW+1TX8^9&O0k&y52PweUE_&hZM#9 zzTC6tIoZApeV8`7*f0L04OK(je zC$*eTxoZXX#$}`J!phER`+a2b%#_tNqE^yHB?*LDm9cCj>XEbQA^ZGZF`6xPQITRN zhqh=x{Gb1vif?Qr+0W=0UWyB7G+QnieQ5qe>5+R$1**+ny;gBxMYgRP9kf*1#B-%b zM@f3}WgcAo<%}-TbrkeOE}v=j?+^A4L=6mi;hs1`F=FbG5RDg+s**FQbzffLmUYUB z`3ip6_6{xfIGvP@@xVzI(Li6aN;l2Mb^Fvc=10G}lX|>Wx6axvs#J|&b0i1q3iFU@ z;{`Ro8c!MM z&t)UpODC34)2F9Bj?#b`p1Q}Klj9WdK_`2I>Vwr{x$meL5DR}kLOwK663@kLR+X|& zO!%kDS&>F;dW%u}_j7F{Wh072S-iLX_MC`M73ruUN7f{e!icny40l2P%&!DvJV&s! zV?tihgM=6s1&!tNC1xkLjkOcazd~UPe6cA=!iBg)r_7r*ID!~qm?jzn9;F;zeAF9; zNQ9ADqQQVw^$$)PC$7krwK|o&-ntN*5qbf>joMYhfp9E>cTxQv^I3&YjHT(&woHba z|HB!Trsa5*3w}Sb*$n%dS3wlf8gTN!9B;Vq1H`0SUz>1KuBUpd)KRv1))|S7MJkH1 ze9)14K=?B*R%eRq?B|L+kDJZ&bN(F#qHrAtk=U@OIpu|Q0w^%89;*!RY{;4${bMa) z!frI<$8BEv&s}V5@ZUV6a_gOP|BP4X2ormDoIV?%6RJ)<$!j)`?Uf#9;F)WX+>*%V zw71lta0FiF@Nrq2=2JW-CuBaqs`b?EHC?EB>0P8ZbbCluNx@>{!Sd$xW99=%))|_8 zIMUvLlYj7@rue8~XZK7vbK|9gXpkgG0`w47w@@aEs%W!N!gy!34)72~zqJ&tej-+q+Y1LZsP0_rMLsCvFpjGYoa5LWIm5(x&2*Lzz~~hid#k89l~r(G7IvJceLVZLcA|B)1Ow%AVr*XjqG08t5KDTG3Xb{@!m1#(s*N1`6svaZJW4C-`K;e+UDko=U-y|umeT~x)yxkK+_e9^M*bXS(b3> zDy*@!SSp&zGB7QRy|i7|Q$Xm5Ox9gzf2HdO(pC(k8EJWeevYY)Ox|XOKp<@0z`Ig5 zgc|l-uC`=fB!^qGwwG~W#>@Ep<(8||pV{qOxzCak?7zLcu&{1i!s!SfjdZNOFHHLy z=X`9w9J3lwhsVN>*R-R>=)%ygQV6VoRkFvy#8Z1vL%`=3mLgE`U!p#Xozf|Yl!U-WjFLt=B?rQQ z(Yeu}gmg)>jqV!V^`j-W(W6l$2ZBndVEo_by*=0Gd_U*hobXkl=I26h+-EW2^TTjQ z)LQH`*O_iwdvVr^*7p1l$E{JFoh5D!t9j0agxY1yH#Olz`CxkliQza$`q?Ey3Zi7d zJc%0*eo4lsd*R}Gg@gPaj!$*nTSd$X5tEnn6w7)cmgPx=uZ>U8UOp9zEwu3N8=SG1 zaUr1__a<1%<(2Z%e4M-T{O77o@8){|q(Uu8&}edW0Bf96tG89^r=9?6IHL2@xn!5~ z085Fr@QeDaeF@mQQ{k7j$2>5eqFR3UeLP{BveQ)|>~u_SxddSr;z1#Ottl^twZwBw z0LH zJL%(FaK{Zi%ots;a{w*ziMM&Rai-jOyX?_|de^55`Q={rDd)4c#N1^urGKpN2XeH*BsPa6Qs`BtW!B-np&t`z)x!RIDj{F>i{A|>6<>|*uUV$RR&SNU9- z?&1wj#_4XeDp$ySz7Gu-PBF0ahn$(dS8RtVnoPC!8|ZBUWt*;lEya01mYooVl__2K zCFLgmtR&3(MGPnr7KNCOU~`ama=di8!Yk0xV>yred(ev2u$=*iMKbu>V5#@_x-8n( zpoXGFc;S2cx>y9rvqz=*EYLX|aIH!Q!P#7{uJCwVCq}F(^gGTw(D>kbZ&kOU=c6+I zp}?TLQElidhS0{@MR}L*cS!>4uelaH{wu6=`gwwpw>~{qFr6M^A`Xw4k$?fXnh}}D zqJzH0)z0-MinnO;hN9J`oJx?y0$827M|Hn8ql&1*j(3IT-L~FQlN!C0t;)It9hdysCGjCta3% zhQ-95G!3yFOu8(lqh$0nU^MVw$5)xiR(GB?Z3CcKG1d|nNO`%A3&D(_7UX3ePtvjc zt6y?{>e7@V9ov)dRPnbt*oR?B%9$HO%Lmu|o?eR>&obnI#0ubvJz|DpaQRt>q#~`4 zVXcr)Cva!%@>muA^Rf5T$*bA!%)(KJf1L~TnbN0Yj7lQH5s|EGr%@3BkI zsiQUeH)y5=nQPNECRmoxOQbW%g_R9H&Mug|Wguz2zoE>rH%H#}Z1e@m{EKR;0`+(w zb4%rv-A5*63p%}-sT!#*^uB`>(cHPdP#s+I+0F;hz^Z5zWMgx&y)d-dMdEUG)eJd-aJFBw z9qyfeQ^lUbam~&2ygPSqgItYNw6!OI%k;CAo6GbDPQwB z+pjEt9BIWUXVtXo#0zycpFu2qHT|=%+(E2Idq^SNsgb9#P6YGe-Tx6im+e2XPrH&{ z{h%ftSWK`wvcHf;w-5b&-uqT}_*%*ohH9muq=wKf6WR^+AyD1W5aDEX7JN-)baI~> zS8WE=_4xeBXyT>Sbo-MUS|GguVrNzh%qrdy;ybMV`1$zCg$fnQmNzuwd2rU*Z^csE zJ(d~gjCV{Paqr#M7LsmQq12pJ%{(}5;8Y59lH%0{BC%J)90fTLD;jtfb}p)aS>MS* z>!nLV!^zIZp#c9fY+TV;WVKayNfn=BaE3{;AGCz%6%%)$N9^)pod8)1qPgDzg;!5c~;rFy|DGcJA zoNcDV_*xq~0H0=~1mJ0g)usD}Qx}ID5c+RP5@A)LqEbJ9=)U zvV?A%=|2sJ?)yQzPBa|DB-taE*0E+ccBL7t)0{stPkSKTg!`oAsh)@tC2U@p#!aCL zr!`{OWXp;+;$DOq}r=ra}r*VMHIE?w3K2DS)1}dI|_PJH5|{fK5j$y zUQ_6Mb9mc+vey~LS$X#YyP?N459@$%3)#*HU}+txOHj}r3;Sa8ZW_kf%4eOHOIvbC zX7sp7h=Yom;r~A{v2&;d?c{7jr>~U_@nwelIuO-vZ$^nl!YALSymXSp=gk+)dGUq9 ztVpdTt3zwc@DparT3gVuC4NfJKy_^_1H~XQGn!C`c)0vQE4G!)EI91Dy-fQ2#w_LT zV=l!%9~F&CTJpOn{=g&lgYsh^ilpSVcx|Z)qugzaJ7HE6<=xTQaGaw~sKcs`dv4Su z-F%SBViIsfdT-0$!s$pdf54;x0Tu~NE6s7M2;$e7aW%88I35gY{A|ZDuPEegsUa<< z2(x{5%S2uRe=SqHil`N=x|{17`e;fX?DD=pmC{gQWL35$1LFZ^w^x%ECWQ`Xhvssy zvUa5j%d=zt#Kl(qKqfWMofTF`|4*+IW}`qpZeDo+vnaSTzp)+d`4;4cie0> zoH9zHerr_+dr$p*;TVmBS^YSQesxU>H!Y)ZO%mXw^z`~G4E`dh)8o&KgNj9ljq<{p z42BN>lb_%_co@{mG~E4SA!A0m6t(ZZ(gkvh()cpsbXSNoS>if@x!8xU)eR6zdp=a@ z_F~TMBrBu5_IvQ0{nGTsOK2|qFxRfgUTr?O=KBKf4iseWC0%afR+~_K?b7oR+R}RO zMtkv287?qzYu77+b5dZ{ta)26`qdT8 z5y_qTTfo#;(O?MODWej-S7$?nyD(*v4pn6RSUE9FTx25o9l&c7U-V?qIfF;|vQ0iE z%_;}c6kmc8ToB4;;;cn1R<9ctt+`7FXt+6;bxPD_u%`QGVl1MC5?pKqp{eDf-|=%ONm*sZx=J&)wNBA&aY}Xr;HeIe;%8^o00h5 zRhB<&fq4Jm^cj!=-43%aB*-ESNtL7d5Es7x@Z0qU|DLWw%hh>!SHBCNq>ZEpu1r@>6*UTIfG%Y6ntU z0VAnLM^y}``E|HNyNG4xDjs9%V`ar_0 zHCm;JM0k;1(Wtkgdh@(W23-drdvBRn(Vc?G)pL_)j9M@fTu?My;o=s|S5i%i2s+|0 z#|<~<+oUAHe9nb5Nc&fpt02|ie!imo5h)c*+Le|2qp8HjHVmu)CJY-2RLM{TBNRW* z&;7@DD?=h3b@o=g?t^06{rdWS=#P>hF{FOu9mzA+I1Q5S6lD+haN90vzT?>g)bNef zNS$q!OlEb|X$<`CUxa39*z*kVm;aWT!dZR9*Q8la47AVl?#@%z&Q!Yo9KR;Fw4Hp- zYr7YZwO-R2a_KaJFJfE-SPo*K=eG39^aVQ?b-z9T7y5{*9dGHhT~^HJGS~2l%imJo z&ogaK&n3K}YaxSLi%2%W$M*MP~IaW|G4l9gpKqTMI^Xp>>WKfW|0=J*O$U38zF4} z^omlYRz?nVzAr_Izsl77R9TixOSo zmKzi7a}IpUaHsr926vhe2#mCZ!nha}{gzJD@N@t&Mj61sqM@;!Cy|FjrFBOXUfp)G z(pAHA<;i{hSf*iHxm@%c(4WiRb9laM2AYA@H;sKkG~$1&(FEN3%s14G%VsvuypQ+D zv!w{&<}y=UYdNt5ckW3i%`AG2k8ebeGIE(YR~+@oqCwVk<-0tEY6tXDXeDMm!Q zG^LVvt2bg3^nP(^g8+Sh=+-)33wR7MGjo|#Uhv94^&v#^2XJ{sb7T1&^poutrN7C2 z>V4|#;HItE>C4H^(AbKUawE=k1FTc}4N{h{G51)x5-Okd6-E?wj$f%Nkn#+&>KPk~w|abNpsyJ*z*@+kyl6VIO3xoWO`LO&aurKUxLV5&yYaSoFqUC= z?%JUf%Ks3uHR&bk@>v)wa>Z)suY=bg))%hHDPWbGe2rhSdFZ)g3uRo4)YM$P7tb5Su`-apKIZ4$FPXEYiNpq znaQX-d^rFE{(+yu*ZUGv#+*e*J3~W zT%HT-RBfiv7IW^JtJtR$aapi_ns(8sqfL*K3$)*JIZl&He8+?sKg>o>GMOP=^NF#T z#};1FyT&9`Lz(eYs)S36DVw@YXI}Xfifklv$Tnx1I_X6%i!c=1v)8FB>Y@qxlxFp; z@#PWJc0brK6c7`WPFLJZye!FGZpcML!`@)47f`%T&qGCYI-`^?G;5y&X|LDbbIIOi zNw{d@8|O8WjNK^`wJv*6HcSyjsCV2W?T5~$@^2K@kT&F?`TXU(T@*g`+%z0(8-jHc+vO5^+sPtoU&ysMh|7oirXigrp#EA19WP?Lc=e&SN8XEd(h(q~(D zaB0Uf+Q2GnVwBoGD`UQNzv9Yv$XthsXkJ!XcRZv#DY4q_^qOeE#>QSzVl-85LFoE@ z)Xi@aeyGV2(%}b|MDW{h6U*Mcss&BGen79_mGx>6ba-Y<(o2FGMzeyk@NuzcE*wbg zadfq{XUhM}ntymmyg) z;edvzlJtfJ33&Bd*}UjC%UjQ3t?$lZ;p9x%7lfv(=kw2R*FO4O{gRB>%lf)%6 zzWU$G8=$MUje_5?VeM&Yf}t*H#j7xf$_o-~F&NOKSz8}cGzR`Ukkn5O9Fcpg+&Yt0 zRwVUysS*x*?lGd(|90dr%74l8w)v~!(b{np*;#CV!qoQ)?%l;&zNFp=Dc7o$r#?0= z!R7p<0FJf%WJLS-02dO0CrQ2e(!(3v%Y-RAw^*M|+sy4@HT@(3u1uf*Y3Fi2XY}&= zUN=E2grYs_)8m?phh#;15C~3W>qj}{TWJ%ytFBzI>1wn){jm(ux7#_G2^gr3I^~Z! z9#4Kp%Isr0_MSh3Yi+T|g`aq59%&i1@rzG@i1H^`r&enzn63hYWrK$2cP(=V9a%#C zomvdp_!xyvRyJ~^^^}XO>1kXKpfBZ_{NL22W0KMI&z2^UvOtikiln{3S(RE z2x?(`!GXuEKr)l9{Nl%#$6ssSnpEOpe$}p@mSQ_pkcCbuXmn1v>1hou7ha#$O{rye z;zZWzdt!b|r_EYPmh*8~EAa|-GI(?8{S^zt;9Q{P%l?&69*%A^!x`RCG_Pildzm;q zA+uVP8baFUaW!H^^FvHH!G2(`hz*YTJYj%dr+J&z zo;58ZCu;j1+pik^bY4u{UC;G{9%g0-fqV6Nugv=F;RVcoQnD!umQ_iJ(GryJW|m z95DZ{q<`(S3jg1_rD!bnq1eE%Vi$P!ESXB<2ICR`(yXC8kxzRa%XMSD3}x1Mh0i8Z$Z8 z7Ogxp^psT)NR2-3MHorrK!_%VJ$I!xZX|O*KH!Vt;N6X*>EZBy+Vw`d$M)SC)oH1j z$>QCG@4gH@)(Nqv)d_k1^zN{rzk+Q`zAj@f(LwizfzXWxAa0pjwnVM+&*@p{16g`s zbmY*bsQbhdc^ErQ*IBRHA;j(s+kHRu|vCghd0Ow8jf{{ zy#~!OzEoOXWXIdd%s+bPc&_(;rhdmmBw>lMQiDLMkE^$hRdv32jtqVDD`s*p^K9)h zZ5({7I#Ch!Kv*%Lsb5DEyeu4x^gA|iw3u}~He4dAdX~(KyxTKzr70yuaOpQM(qJv{^;6#7#hX$+rq^28Gxx^0F3dmuX!%fEQ~u58 zUb@(^5}WX$d5TZIx|+;Ac~w(FomcF}|MT?jMQiife}L~1tC`N@HtAg-O-;+M%V;k( zk914qD;uug@LELKyj@wMSEa1zZBpG`{o2nB`m->1w8?dIx{Ek5LW95JKhzr`mONg+ z-!8$U@GxY}sFaH$M{1-My*OMh4`{6@gh0qO4USMmeasLp1pYcIQ&Tql;pZ!;>a*}+<#b>V$BsqbEmQCtU&4(_<(V3^}+q&y1^=hx#S=A&mPKa%)*})|J>}Lto=o`79Hm;f` zn~Yq)Ocj|n^m?K!hjemm`zmy8T;15Kx43jR=bb(wpVJOviU0EH0OXSmEYEC?46$`) z$f*kUF4ZaCE>Duu-|I=dJM$FF z)m2tx@oHAn;=#2Rpng=8nC^6j0kjmX2%d&n+`2uIZrFT|ix!4)nj_kX7DoY^zp^h! zBCUkL%%i`>Vglq6_oCsv;c_i7^?bh;;#XJBpbmt*W`Ybxwjw3!I_=dlH@!@fSMdSKL5~R16iPd3mqaexKKSD%v23?r_{Yzox!;wJ5~ci?RBej&3g(|3aGR@Pq!Cfq55}RMSoqxScdP zOYO>P!uUmSbTKmS|4uPqDo@~_|>}^{~Y^!C= z@i|nfW`p$3gkI#WQof0avB;IX`(H&^PkC6s-rb+ln_yvm2hj-8;MSU(i;*QmD|iWZ z@pqQjPe6n~ka&N|%_zQZ@>kz~E0z(249|>{Cx14uP54|5H(}ICRR2`k)o91nSJMF7 zI;HgimSf3Y*c!KIiIE?Y?1jN+X|KB!mf$F6ur+`P>*=D`C*K75>?rrHgmah1U24>b zc;Lr%gRKf9fc2Qm$SdG1o~C2O-&^3f*%CZdw_Ly~2Bw`7wIyQH*9En>q!yMn$2EYR z@Ua#`ct>cK!KdGBGLn)v5p#;&q}LDqGhbq{4b7Bsaxb5ekv@6R*stNzfCWF46HXmo zJT~lXLA4J}SG~iQNJz z=j>32DLzPvFCN9*Z5FR_w-yWU1XrNPW)4Xu_>L8ANo;q1BE?W}b1)osb%yNM>|?)KRPmdJ%{PEf@) zX6_Nak!zb+kcfGlKjndOuCMD2l7U!Eu2xvXueBI=jA=}R6?X=gLI^)p(H3~Pkq7A2 zPN$5DXD#&jP=cG8d$cH_nuKr4j*NYk)keZI+VdRX0_kEj;|F`N$QScBl39Rsfc7k^ zpsJPE)xQPqnOVy~sI#mR82ekht!T1JftU<3DI$-c5!-TzkOC*x3+ZmR1mk$hvlc(f z{yO(u#j2&+{DsUNiFAGYM;}2+gy5X+ba-f~(@r;<>`8d|%=hnW_#ZCigDZb~(NMN{ zvG6M+0BS{vsU@puy0Dj;cY6^Nj(_QiuSIH^H}hpLk;hMqI~1Ga=WtRzwMn|qG!_>zTim@7qeHAGF72%G}KpYI3_#y zSj}rO0`{3nt9L#bTcF{gh~?b@k23CfMK{gNB%m$&Q+c>Rjnl4+f+Xr0yez;1$zT+h z9XAo9@kyuQ0~RU|sqzLb3dY6c!{vc29K<(RNI%{83)28^=WMZq&E$`Y1mx_*2g-!B zQYL6F3+m;iv%GyjBZkm6xe~FU2DAXdy=~c76Qo20fMd+RmQQLbVEU2(Rr&@(^csEsSF_&`sY*xQ(p9iGv6ncF|b z|5waQncnU-pt9dkUG#r!;7VUU%b)W{m4)Dd|3_qGfBE~h-i{^%P*WCUHvUyx#nsl| z@~)Jbih*HvBAB+t@CJdz)k-`~FopIve^HAcZ)N(kaxpxhit&CSJ%^6lly>{~yRNw_ zk$?!i=8bN^P!`CR8;)LGS}nN#Cl<&x8i zk9J5L^rr#Z^t5xc3CX1>Ja0hIweoXk9(ac>E4nNuM-5WiCz{w*+GIYm9Ei2V%woJLjEM7M!LE}Y9ek#t&1mx?pQnd85QyNnp4 z^kh=zfjzZVsIdc`+k~3Vg}x4YadN&uvfhY=idAdN-FArwJ!^i_l)e@m#1NS9z{u|QS+NY<058>y zmkm>;3iHCTL{`~F6wf%?Vn~R&rAw64cLLaJ*0IovSutvrtgo_~+WEI>oY>po*NC*i zmCd%7+4NY`k1u_L!X+f|W~{ygOiQoQX7^#FP8|+KGs2Y+SiIrSG)@yKhFuFOiHvgvkGTc z?cpOeN!*s{!mW2GP9u$gWmWcnhW$xrleluaoTEnhU)7vEJ7#)YmRrfmq!>o z(QCJS-ztjwP;%sRfBF4lcYG_V3^>A}TV&3Ap00UyZ82+eIql-my~ZlDUS&QMHSZbR zRN9j9^95REXHpb}cGm&euAVK-4r{?8<|EQ#kHF_@Q43jRbQ^nJ(OxEHB)S8B>vet} z$1A^PxjRaqzU2*Vn8=GRxfpR5n+_jFgSIxlTv#tBw%Td)?%FfW)w-#?<_nUH#|l;B zytue!JJUK$m@K@+awA9HhYw|WJ>rsW5-sKaDN#yDR#S`id%40sMjWsJjqXM z>x#wA;wlUsIJ6qv&^Bg#r~$K#r6`e83NWqo)$+VU0)eEfO-B54Y@!(mBt&nkX=d&n zJHPZ87p&w7pm{{NL>wyW@tc}x@RQb+jFahAj1z^{(x->~4P1;!ZHuNVAKh-*_*o^g zuDWiG+AFE=?Vcm01^^lPR$2gG%7R6BY;(=*)Z2#qz0$T=Ok4*&)hiPYaz%$ujhVy) zIi+pzi~?2_>s2UYqLgNJl^JCF& zs?w?uJ@2*FrN3&KUN@{xH1_5io4L!CLo2lab~f22MP^(MB7b&JHLEeRODo9mEN;Yt zQPOhT*YgJB2v?q%w+pHIp7L$Jq}ZD<@Uh`W{8)4u$Ck~#1XU!B-UVjv?r9hI_pt=>G7Rdzh1eIs8plI@m}_s_-c#^DIN^dR>DwE0J-Oab)l z#}3XW_vn}oK0q&x+xn<4{@K64TUg1jw>4CSYcJCp{_MHfR{R4bzT(C}K1EZnQ1p}G zYYV$NRg#k{$xWnxMVb{>vNpWG>Bh0)bZh2w*6|F&8nsCcg7udUvoD91v1jK0jrNZ) z>5knZOjKTlV4&Sqfo#C7M6f!U&uM+M)#0O7K5}B}G@9JG{dXOArOxy5c4j*VI(W@g z>0$k?TD7xIK7hs2L30Hn5e4uttRlJ|zGMSEXtW3NYX!1k{jCRQQ67?&{YpVgTKf1L zsmfn}_)%!1 zOpUo$yD-^;xeMA`P|I#fW_V8K%;;FGXzj86A~~hiPdRk~+QWKZj_T`(nK6KY-6ML% zjCs-P5C`OH*$2AY(~YO@HCIWXkJ`M*&jOPUdxvX7ct?U=mRFv)Z5h%Q*3chi-v=Ko z7H&!ub(Tw#16`U_}D@bZ2DPM_JGXEGy)7DGcCAEss? zG}e$RxPdUJ?MV888 za;Gv&71_b*TYZAXzKw%xe_cbkNt@4Ka7<4h2W|1toLR2k@d^RSsE*Iw?&`w7op^iK z{-=4z=!00pYj@isIr7-(!+U0q%zpf#J>A zslkT5{HT||T-eTjH*T~)c=LL`H0Fr9N~QU&s%zLC_S?}%o!)_;zVrc6*DtWhHCOE!&rlwEuz3>U2@skgUrqOC(dh zLY1IC^K=RyD@M^6K->ZnO%(s6Cu$QOppCLI7dc}rjbF=OcsbtBxlnZu^Z+JOu!oBN zwC(3VbUfASMj;)v!{rBGlv>X_J-jY+H-@)|9r;oIxwF5$If9x7PWM*wS`9dEc%!|A zJdksnEtkD@Y`v0ar;~kB8D1e=OHm$mYda<)0Dyf2Bx)Id=%+Oc^FM!*{qR-}NXiPA zDd=E&R25h8>~EI$vt4F67q(|uA>MUUDJEp+Rc%an3{*X})f6&%-CW!jMkNS)9B3S< zyc9I~Pos4=n&<@*S=V`wv-4!b-W8vm z^zG7LE}uZg>g2{JP zldmyZY@j_uRBg9&q*r0(hwrZW_M6K;8wXb`2N-7V>IlN0R|)jZm{E@HErgp7YHx_j z9s5`kJ_r7ZH7UE=_u~T(4!8FNkwG&quM1*>PG0WaM}jiu_)kWw+s_uAwzhWenkJ*q zb5?HkOVG3)1BwmM_U1x)yc2&6vH{AwEOZ+&G|ge@%~8F&SZc6uf;M@^L!P`dwOY<6 znzLD+>k<)yhude1H~&PC3BQMVfB8{mn#}phW`lL;d7@}qNfP==Ze5lPzxXTAab5XR zQ%y%ZtV*30L985A4PLV{sHL*Bs{&#BGE<*L~%&1A~SB8NEfMNpPpfFj^rjba_^;W#phxI)=#-GM&;*XSl2->O)_dXUFary?a|<+) zh9jKO5;Y-yZgg78)OXU;#5)7Zg!fhKFUr6`KSGB^Bj|35vFwonphdNwdtLebYfbHR zeW$;))jMZP{x)VX;kcb~c!;aB)^b!ga6Fx{eJoJAifR>e*U%@BdRb<$&YVCdzB2?A zYf|KW#pFyvoy1JVYnZxAv@8iz9IZ}VkrvB&EB_F5?H;+7VE1=@fZoLPJ1YkZjfYSx zECeU3Z4P6x?ANLYs_E(VIwOrRe5~-F@Ue%xel*Rgw!7`Gw?Zap^9$I!A=bmrHG}GV zx}Kr*jl_@gxOwbr2HV&8lr<6#IqOJe2>Tj$t-hflvbzzhpYRYy%Iw;(B+RTx|0tur z2xFLp3l<9O7xi{HMK6=)Pu-{hk3ZSoNmA}b(MuSyIrDXB&STj9jmH!z8_Q_cZvA@e zg6~gJUH4kok*G$NtTXAMmsoq`ddPMEU5dMq=iKK9hR%q)HsztILLEil61Dwd??f0c zp_QAXivzP~?q9~S(|xvF+*$m^M!I7Y2Pvz2HE4y}D;NMFvM*jkOcbBmtyxP)hz?s! z!=!@xk+F+TGEIxMZnV40GLga$NkNt00eA#WKl_f!|IoW@OavqmLU%V5y)-tb0biI+ z_p$lD>ldMLGWOSjA>s?XP7B3jk&#A*w~DQCRKlJM#h9up)~-h`7S@+h*|p=Qj7pZv z%oQ4q@u-#**F)S7z1ErqP=-S85x%P*gGr62gJTDBS$7aKjp>B=>GAljG}Srqdax}< z^t>=z?s%-QVMQJ|7nXaOR1XRpAbui68d1p7Dlr?|Ln*xF$?`Cy(r8NI_^SQ9R?76- z?m}mcwv0QZ;1;oOotW#zywR{9PmbJd9;~07@UnkB4fW+xx=gPW({bPORy4NR)ScwD zoon@sY&fvRBcRiCGm~MX%LK&0vfL#0Q)>FS#(trqgWKbT*C4r;FOyA2oiXi7_Dn~K zN^sU!kv!Y>VSY;)o(CM(XY&HsDJq^d4{WjUiB(#mEH7n zQ`fwm3pQ$<*rv>A(3j}dv*!dbC2IIy!!XGl0boeIo!8NQw!yv)wRN%CL_cW&-oFO z&3hqr77_CzKe`CQOhnVPUWZk#Lpv`oPlLef!q+bk$b{#GYZX055@lP)*$eJHcKgxu zua!>Xr-i=HLI(%iCBt>+G2ojIp@DV7+4OR@dn0wHA-1Wz11}spw<737B~%PgmGcpJ ztX!$PtwBKpoQCk;5I1LC2>5kk?H}PVZ*3=C(9#q_FO`o7dbywC7zH|Acai!Jpft>| zj~V73Y(HDyh-k=qZtN{dOR@h#k+lZ9`kghY+o z012W7VFv+*88>M`N*i;jEL^L)C7*CLR9o~;E;=T}NLD}irxn3f(k4iI<6b9qF3?DX z#>1X*`jmRd6y&up5zO>HuFcn4MEyEZXh2bq#)Cs=N~k~^$F1x$g`U|2%53&OkrW2D zory3)xBF#)a6VJ0`bvybjD`N_Zc#yi!#X5bZi=REKCR)(x-Z-!(PDG45KHXd z6vv##qp>(--~POY0*$U>M$XRRp6{l8PxHp~c6(0Aht3wd1YCgCH1sURdJP5V2ih2! zP8>(IE4#CQH0m&p|EjZOY>HZry82I9ex!(gndE)Jf15XZh=RflBq;lbYMMb+#QYQ6 zC9+Ho)r!({CZSn176)?07&*ZbOMHYe8;5*}iJTP7tjk&s%Jf~eX{bv?&@(0N1_rp; zkDuc^v8*zz9oDIRxtu%;ge>NCh8a74W;V1g{!zyq&Sb_Lf-loPj~|Vtr8>8D?>ApN zqIj#I-H%9_9I}$r%&S00_o|JZndUf_ag7!{H#+@?+N-A)NdMzcVbu)Jy_yzTsQW5; z(}ym3Prd;8MJ`*~Hc?qkv&J7AW%TS|OKH&BR&a=8<48=JV7py$Z{d|B)oXOt zUO6ry&D8|HKd`DMCQWOTmUX>WKP9HpnweD=7e zRg*+>5ek`$%a-tsA5EENL@Lc;qAl7Wo-h$YLCv9Qgxe2Ur^VnD`Q<3wooU zxonXO*K3N5($dTvjIT%0%~$e|zkIbU$-Dk^4PIJ~E9=wpummnn25V>g+>NN|8Q8VE zWyCtMR!{AWY7%$NHrOqQ0}HxXoKk{G3sbP0JK`2e zets|=%wydAB|GQ1CNR+ZCE&@rjYh1LxH4@OO=kiGk`Vj4(64%S%ppu4qg8yWfKWgR zA3uNaMD3~=N!icC>@B2_AxBi5R z5WwdrM|p<#Q!^M2OBa4TaMyd@!Q=U(qSk`Pcao|Ftr`a6!@wfBHbi?Lyt%ZtdWCSE(?KEn6x1 z0$TNQhQ*qHU$>T(|L(XDK_WF!y(Vnq6qa$*>To~VzZW+ve&j=*o&`EadX{8=x-9r> z=U+d9ji=^;rXS-0XxQkGg`A zo1CVrqU955CA+01b-vt03^qsb0zBrWf-!v$a!dO4n{FM zs-xB{IORIpp>>A^a9r;9C)Z|#S7R6BB)#gQE378tE%j8K3vnmf!skNL{26uvbC}W! z(p;=GXLI{QU&&r(vFTk=wLPdH z2D<`#-$UrSoAE7A`Q=nYOIV$6>;JUt)*?DeTV)kXt!{OT_>L;(N(Sl_0x5Ez^^<_I z#wBnj*OHOm(YB^8zyZ&Hy#z&7s0s4B^pih)l7MV`VZ&BTU76ScXw29)vS(!d%l(_I zm6kLaPhEHoz8N__~x6pyQD&q_H79`#{+MW9kbihPc)*LhK%~GvH z-!$yJODn%@%m=XFHrT-t5K4_V9YKfj7`r7%NFi6ZW1y|~4< zB@zo8X~&4m1@Nz<5kQH!Fd%(ew&nCT(V><`Z^bI#M$fzY^R-M%Z58nZ|Nok-72$(4 zRv11W@FhKA%{XV0rR&C2Qb5zn=jPGGDFPsuUJFG?41+D_c)M3mi$~P3C$>-)1yfSl zCd_1p->)wPL26o^K~?%q=Fa*tE1=3|YQ528dXDaz&tgyZyF)X)ZR2rkn}(a=T!u5I zkILMe2}hrr8P<~b4Xj-h=hXo%arh`sqf|SVxo(*$&v5B(;F7IZOc;{vTwTZll zf$*aip)!)S)PE(_=5HdRxyW7Vir9;{FcvjnfB8CDD-|Ju5DFbaESK|fI=JCw;-j&b z4vdGY)2lf65t~kkhp}T8Crhdw@yQ38)J#c+8k(&E%_4v?To<{KdT-Pd%SPk@LqHPj6Z9IxEj?^P60E2tnBD?&|0B}LaOBwP zHBwneRyzWf&!Wm*na6i{?Mh2pLD*~cpqX!LW!hiA-v0YrA?xmmIbi+pa>xMtIvdS% z!G>)xm!!=YTttzK!nEXJ`6g1_=eyKyXl;eODIVO`5_-Vz@E+|Q@m@h1&3QPu>JN-P zI{Xk#pH0VJb526+ADN9S_}OGN;JA5%I8?4YZ^pEvQk^cFwo_pK;Z5*NAwG?uYXP%v zW%)+sv4>rJ0aGR?VK^FEza&QEkR%W7Y5owt>E2y+D13iIN{L*|4%zEPqYdCX2LqmM zM7mv}W;LrAj;BHGE_zi?>2bIi-~2gNDJhY32WAY)#32U*^#Mn59N0B-6pBp7@a#4N ziYax9l%F}*E*@;=c7X#lJn~Pecr3ci87K_wvmGqrF%*V&ZApve|5UMmM)IDRv^HI$hVkRq0JZYGkv=mi1^T_U^?!w<#cd>5ifZERl z-WzBdQ31?jft-RLP62= zZf_RJ)s4dSnv3@jY<=Wb0IKdW;pI5hs$PTLDyVB|R1#mOi8tq*LRYZj;C4q*RkhF? z{|_SmmV^4kw05=>ilL$7OXPx5ms!WXo%UH2$HKY57>2`QPrvZXOh5e2DWG~N=jcsZ zJCTDrtDLA`Z(DjhQ6E!PNY`E%My(h4OW5^_(CjW3e;W~euG2j< zccu0{ey;FM@87L^f5!opE=k*Yt9$jWQrAm(-oO26ktRiL%0Jh-b~VdM(isBBt(eOz zCEW}XTp@%{~R4xAIk?5!+ zy<-YC9HdjMp^vQgZDu=^V!0v|SOnZQrdtwOLS)F{mUYRuNuPxyn=Ica{^`-B2q=j& z`;-F{TPL>2;NJJ%`EmV+H6O$_{+4ht1Uz}UK;sm{{MtwV;+BZ`*?!KgmGc)fm-i(K z7s0yeo1`LzSfLbsqY{1}VHN(Um~c6P?;%bL)I`(cm+73<4KFGv&tXROP9j)&dUd5J zAqYrNHMwJ5kJQ8a!b<)nP0PcEMXbu2>2*;{<2+-(bRX@?-T*>R? z9l+~j^VY@|n!tn!bJ2_;m(<7v%FF?E7`NJ5J%ar(cE z=_0qe>7DM!2I6MQrrb9~PxricPIA#fTXCB~WMaSb+T!Gh?R1eB;_ZsdlWPVKT_UXe z`Ly)bD%@xH7M4apA77f5xqp@kqD6HMX*AbF`8n@y&re?9+BK?& zERQskDl>G25;(84?RWH?v!72bca?Jp*Pqrdzfi&qLNJF2==tL8JuB^}Jr-5j~f&p#UBnUM*ptKXwK zC^tb3r>-s?{ku6i&$xW<`~r$PO3-@#T(tM!Nl@?y!G-IG0U1#$4UNWTj6eKn+-3O9iA%R0TP=Yh|Uq1y^Y!Bdx?jN3)eZSbm? zTDPgIxt+L5-hEv60d0}O~63{+gJ*ntA%}OYHPU>-! zflZ3RhJOPtxw_glUdC87U6uAmKcn^`)RmrBT9RpN)8?dL_Git`1rf@IEw922RGHHn z;+L-vTG6C7$U_HE8Z+c?J5Q?0PESblA&>zALiE*2;-5YdARcV;2KRQwzlfZ^rCjns z$^dOV`P}YE^o4`5n{=G+ts*v|S+uvEjeS_9gm37ytPKSmHjT;i4`_0W0jy0t^cRdH zd@lP!v8mI$W~i4{dYVNK8h5-5IgD4s9ATof#Tfjap7&RZ-+Xw#F_?b;8M~+cIA}7s zJ&H=V^j7rj?-29-R8_jr0S(%9b0_9!>mf^Fb9!rWCvKv!X!qK#r2UWTyrxJ}SP`r~ zo~_|$z|Q+6vj=_Se{Erjd~GxN(T1KjOMG>S-_m|B-y|CnW;-r^WidB1S8WG`pyaV!0lDmT-#EAX=DU!zjarjZ-a>B9P-4|M=?hL{(T^>xDnCkcb zqRZR5b9QQXe-2bXPU(KM_lSdl&_F20*0hDLam?va$(5SUDV;Q4c6r)vM=5dz?s&O0 zj~cD8q0Oz+a2d+A<_l(0)3F6G$YnE`k#af!Nr7FKWMRadjX$}0D^?em@}`@-GA!-k zv9m?GfQ>F*d{D1@EK6YiUwq}1wGd-kBR5!1#A{tK>J3;5)zf^$qEK^vo3n-#gZme# zwkyBg+l%M$&&PC5h}VA7-yBCJL$o81v;mww?CcT|1+0%Qps@9nm8eR%3!008!lib2 za&m{*9pzobuu6w*6{0!w6b-&Yyc}M>4v6I$*Hun{p%lYYNCT$K3?_I!oKtT^F3lYy zir-dW(#FzFA&{^5faBorPm0lKRwp{0oYLjy|8YGhNv;E?=J~y;)M0tMiLB|VdB|dP z5j~g}C3O`Kck{s#_^8Liy5JJ%0QBQ!fee}9TszMnaZ_sD@)nSdMr)cjnhUOR8}f$6kKGTxB?z!ov-_6^9u-F0S{`J>67VJZW^wV$_KX|351K zAm()-Z)3E)%qxtFG}Z1z!3H$idKi|g>33sFPSgg^?u#Z7^zt7>bedZRsx3vtLhbt+ z)&z13vvjEN*Z)T)YdHxh&7?(nKb3jr{xzm|TfWi4ZlFL&z#n9FBzmAT$*qPJgFUqA z*!kLdOSxHDj>4hToW~Qhp(<32k&{6Rv+rvJG(GS}CNlfO&9^hi*Kt$AMQw^S3k!F7 z1Fs)Sn-pozZ7(qRRc;??>YaV}a72{0nga)kya-aAfmwIa{iv+QzDSvOOqD{JjG5El zq}pmhoa*A1yzJ`%@g<|KJ|k_73%pgjNV+F?Ee}m};G@JxKU4*FS%_dp`zx0B6Lhza zcO3v;d-^h_2I$>ShIX@ef+F((t!UkMnE)}QT?Jx*k%qXaCanA(X8wHXMhRM5&TTv2GRB8S z*%-I^1g^PeT_z*jm!9c0zfCQ*qI(z`Bveucp;QeOs2-?)t-3~1y>vg+MKtHvxh)f9 zhTj`!!*@C_woX*x?Y=CQ<;r-#-2|h*Fy;Aqj71a?9vdrLRf5~GOjFJd!_CLk^Wt{I z6kx+y#An%N5tn6zc6cE+;c0q*Iswr0=$8REGR+g$7ptU0h)=UA2@IA zoEKS0SAWbm^^+Py19x4o`<8r2o@+(qdbv;Kt-WJ(9snW+rb=yMrv z{>9e_>9>kj>pxwrT7TAQ7W|Fw#Z~BS)WKcNru9^Az9WZmRuhw^Nyl~uPu5WN^P8Lx zzFvf5;&P~^C(FR?(usY-y|^Ksh0iuAm*;{1MMj4I{0bK`s1bCeR}#W|^R_xlRf69V zdN!(1N&SQSxrxsW~8!$ zPDZl8jYdE^``*OZDkl1W_HnJGARD}#Wt6X5bD~3M$-H)xOr_|VGw&|BHmVk34!#tJ zrLwUu=-W_VdT=5UddSm{q|-V%FVo|E0GDlnJyLHhLwG~^?Y~Tlz53PbiZgp3l|5ue zTeW0~PEI0U-%HzRvHFT&9cp4_&W zw^x-6v(`bCcOKn=8>sr{1^SlWTV$O(a&=ezt>Ky zPsNCa>HGjksoP(kshdsGVI_a|3>+;^S4k+w>tWg6;#%*#ObOa&Tsg9UT+92r|4eJ5_f;VF8T<%Xh z4KMF=Z9V9y2b$y|!pm3anBk?=gttmR6xOKNTOFj};&LEsyeQ^Pg7y;$+uaT|4H@?E z&`_=PBzvX&x-8gHU7lA<;L)~iCa?0-Y$oA*KIR)$;nFf}G)uQSyxI=Gv$P65`q;KW zF{)Z8Wdn3=GTuk8()>^=jCc!(Z&2UrCRf{NaQ10kn8sQq;h(6?Q-LKzTtXwziF9($ zMEDE9U9z@!m77eb&aH&|?9j#~9X$g@=IlS9dOtpLt^BZ|#{&4+Du20<%>U8K?3k2d z=!#glYL_=*k4&m#nf-&v1Rxd+Spr5C?@w>mqjGe8hHIRv8GGgu6w|w@4%0Brm*Q{s znwPayl!|7?u=8dt(;TaYby-Yc!pxB6n{ghkqzANPvGZ>%}G-O93{3n78x))7s?u%+S;=V>b(~O&!k-+WLX7?~@ zPye?+Y_x@3diPb&y-v|X&BxgDOg13bxm;nrOvBrG$=AFi%VP4C3qIfFW4W0ImVMhS z%LTxQ%sz&2X?om01ErJj$Dtqub2v$n$jyMl9V+_iW^MF0-r7dj+CpCKl2OWeN9Km?P<@@lb$|G z%h;3KF)`w23E`LcdcfmM3edFACK|PM{L}aWG{#TCPjc1q9I1h9O>|b}Gm2{~Ck`U;Gc6D0(EFSmnw#C_+Kj^V^~D?JA$ewT)ys`+i=fAo!PP!}O-A zG3~6yR-e;Zzq%3@Sf_D0ZnACO^-K?FVwG;}T9K;5l)oI^ie_niyRoM%ns}u5F1igu zugLPOA(mBy=MKmzGhK0Xd_hT{p%14JYLKxAIasFIcyaq3{ff7Ik-l)`$ESC0arQX* z?xvUrGP6R8<_hGlcK2etBk~FrqR}(8$0>)%S%n3hnhGg}H6@;#)dqVyvlz5vUQ^fX zI2?ZZw4+Bu`Sd`4vp-+j>Y{Lh*s1kqB#GH`v7vUxYZ!wNfA@f^PxLvbU%0|sF45b; zrvf?tqM;__=DuJ|;r94E>Pr%ZU{jQBwn@&S+4NjrZ$0rEOkGwsSh(sw^ZD~hS;9T- z$Hph;bsgOkd02-79wwHuSZ-Cw>&W>WM4h*m1Ft&-HykQqBlm)gMpgmQ+8N-d_%vP; z@~8>TZ&Cb%lDqNDIG`@ZLPB!N5n2;^gVw)NzVlFc-maH=OCL)jj)IB`BERahp+7o+ z3|<%$s_CvGl}o&U5=ET6BFQYkK9g<6+vBDho&BS`q|D=i#N$DODG%ZrS7u5a0`8=p%#GAzc>huXTa1E3hAYrTs(eM7!&;4Z{HL?7&|{ zzRq=2M`=o5jK68CSJX3^1K>h0qfd~?_m6)SU)B9;*YD;sSi>gw)?I4xe!Q_F zon)j`<9?M2%?u+Dl-n|NhnU0Fg(#v|Sylkx9-U-#!7pbCrv%RtaAFCj8as?DMn2Fn z=I{?i^6W`bobK&A8stT(cUHS8w+e1W*%r|Qvlw{sQBkq8pp4y`iZ>KZ=xtlGvbu=d zz}z#Rn?^5L1x?0da0npraAz7efM?&H!s|73a3R%%G>l?wQj!aA|(o5N5r_vE4g7_1=$+i3_o3xF_qB!=9(8)2D6-x zGxLSQlaa+jx;*`d;7^GtS@QDxr8 z8&kkv-C}0;!KPeHsM;mRoa((X%Aa51`hXnNs=>LD^ydsQ;EQ}6H>NKb*>mpFHKaM# zF!VI@9^W*B_?v|a!W+%EZ(D95It=?jt8d5G2vTYbNoji$U=Y>~T6vYNXgFdYDonU~ zwOQxK0AzY^sQ!k5963lRYB!U~!$`tfj^^Ux{VF}IdX}EKOd+qn52?0UZReDXDZrKy z`IuV;QPHB388*Bh3Hy`Ul98dY)@6Cu0a@!ynrT~GT;unrL%Hv*Wk9JYtb$;3^mw$T#t=#C~*y(JII15%54CZc2PX1pym zl|YT7N>v-pT9Ge7dGjr)1xUKd_xj#Z6837vJJeJT@o-V*zt0YSoY9P1Cifk#$0)I> z+T^9$T0E2Ybs=_R3j6z~U!_FZko_77y;Ghr#}%2%kN+5I+#7jU)9_*dftplM>K#)2 zCFy4oA^^&b>g+_JAkj?od566LtXqF6rPAAX$=$lEkERQpt2gbi{>#JRdDf&i>27*m zJig`g5?~2}$mnT5%guc?NO?TK4#>BHewV`NLpTv8$%*^mn(6xaR#!aat<-k}+JtsV zmkL4|S-tuFVi&E!PmAwoJv>&bbv95;P3h4qJ==FeQ0M))t*UxwqW#p6mG8)(+P9UK zms!p+MIw*gj5jf+Sn@m14@oxlUvM_mse|J`#Av2>ExuDg^IHpsl~R!wj2 zXUr@}7y9|qdA28kH~WEGMeSt8sxDPQ5`CUNd=gW*$ob_ns}i4fy0g`hnz=#^NjH-* z$CU>y9{C3S+13bkUO``5KBu;xWe>f@>nGOdA2Bc52mt~N!DT5Ig>8BKB(^M?^QJdK zrw1A*V>b7I1HUN%7bhcd1$CR;5~VV>jUwx678IFHlMm5jZ+yb&XQ+QA$k6nBtuYas z;=8D&Wq+ai{0>-jH~uu07L%u~6jqV);cVkW1{V-fDO%#f&A|o~eh=L?om7YoQ2$|O ziII9EsG@nvY@j?4A9CoP8zDoH?0zso1JH-m_&!z2PRGk+erLcIdGGzw>9=?KyRM){ z+)GA_dgVu$M}L&cL!sIg1ZeZ(sx{g{Nsm8_f8|ya{68w~?n$pTHr~l_mpWDG$|oQ-dVf zMDQn@thSln5pyqe2eFbQyS zQQF%4{BM8-aS1K}DDIwgYtqb$=MH*WEF&-yDx0!XM&cr@j?2~zQ{Rib_TW|O!R;Iw z3}QBxj_M*D#mF+H`(L{FtvX`+mGAWowscb&h~)mTj_3gx~NUNnFwcP0`B>5_NE)A!R=OyjOvLb1GYOf&MV# zm{c)sp#QX*`Aa&Z4NaXud37oH9MxFqiZh##Svsu(H4uIX13Yavssk3dQD?kY5}AHg zSP)(SkfpzRfA3p}4Pq6(@54o7>ThNN#3cnJlGQp0h-}32m+#C_Rm1JXG3Sb>P{n;M z&31s&-NP!e$QFJedY(^(!S&Ju^{JGKSSkM8o~_y0u?+~6x0kR z6a~}!CBU9P6%j-(i=oIG4gX!)=mU9qq)g8zjU6lWlz7&t)9BAkGP;#JAD= ztYE^*SPvFG39MR^nwR`OeT_P)Q=^fu3u`@>nSUBm``W$OV&H3&8`$CQtzdsS5`{4m zYJ08GxNZ4GttLXy2e*QOX<6#jwyqo*Ni*z0(o0E4ga z9c_axl;@*=6h9vPuG@w_s|PwR+lck}jezne#o?eD&*}qdJhV3#&0pgnF z&wL{7bBiLwbWku7WL?5Nj@jwRdwGcDLoV6#sLCKqb}D2X@d`C6+* zwfRW&eL|zFod0O6l~#?)cACjZmCjf8;=&5h%<;GJYH9ST(CVe!IFslV)>r2 z$Hy)5E_H$XNgll+Xf?UZgYkighH3kKL_Uq&WB+o<`r;rZ(O)1hDP;?)7rjV#^qk9d zir3kWxThqQB{VMswO5XZvW^<(FIQ&vay8&&|Dj^w2O6=WOlfbNwZz_z*F_z{{{L^ zWW%q+|Dy^_RgOt@FO9fYooIcyP2o!Yii{AhUVUy4@t^DG;(whnN1qm=mP|IqE{18v7Jg<> zoI3w?@X0L&sSn|xW(--&xb5s?8Dx+a8ecvuQ97jLX;Xl&Nrd}}sTuz(QG>t*oxN#( zi_yP}paJTP1&m>_fV^ni)6b`N7f83LjvKT>cEc0V&$YUM!aYkZp7cw~DJ{lyhjgzl+seS)LiDnn-hpNj2-`#FV z=?-U7t!zO#(!3QEWHP4!HVIw0r9O$d4n*?vpFUQ4;;G}~ckp`qHuCBQ$_`^==+uRm zsXeY;nZe7XM7Ixjz689=2R-hQOJ2LuQVvTgNWHrRIlg7RRm3-Gh(li<4CDPAA6xX+ z883$SdD0+D9+-*TjuH~X-=%Ax-*cR_#>;2FufBJQS@f@cl3@Ez`cSe?RDoZelM(=j z+Qsc#={l4uaN9g-Gbh&~40`h>?_QV(=(d}kTagNJM1$xPi?0Bf%|R$Yo6W;u*(7BW z@KP{OGu)x=l|_mA)w680+;6G01Czr3%nT5zw`J2G1JRw5;J3`I?B zxf$CEc({WN zp02;&(?Vl7$v=SWFe3I3>0XFrS*SoN6&YWkrW~-0(IK8C;Rflz9t;3{O03jP)MXi3 z;VB15ZNR&#@FQX)+-Bitb5R64B_`8f&g*4u?Op`d+sbvv_u1`ZZ&}Hbrzs~%XvA!> zkwfjd4~k_7EBINO)I()9VOnc)Fr&zAJ9R&9606R}y*VdSK%N~5_64f2^t60&?W}mn%{T{U^xFzHNMhhP2b9MVO z%$b4>l0|ECTz`LG_+=t`l6L__`=oP9&vPZn^*DgGFi{aS9SXh5C6Avu9>%RN5)@3j zJ$=#BnPT(OvcEK*!mAgGgcW{ydI7ONyLIp*jC4%bGb@eBZN!!Db8Ns&&kiKv902h`S!_#)Mh{U^-fser{W9WS!i8d*yO~8+|y~3E`Y}h=hO2g=N-^MIK|BU=OuXT_>|5wD`ne) z+E;8YfjX}~$l;{gf8`k|aP*ndPGxZVY=tp@8Uq7vaIfy`A$Z1fxL( zam=av*Ld{&XmIrF)*IR7o?R#A4O-i2JsD%Zj_aiNqg%iDLRxG%s0uEO!2V}t0Li~w z80XuFwxa)|vH~(1Q5;!5OlFYZy1ciKFf384bf$w<+$Dcy;bU;q&ffT0b}Ldl$K|Q& zqyM^~T=<;~FoY0LKPfFGzivVs&k`C~IL8(dj1?j5AG9*O!1E=rUY64G z)8@z2biZih#LFxY1v2>a-GunRvA-t?C0vg9d+XYWuRl}O05w3$zm?Qb_|C2B33D>H zlOq>JB)A2FEpfkJ-nG=%`&hyZSx8l4UNb^VRg6_OXcgZbt^DcW|D@HKm#|7Xb5sGz z#jVQ7yx+w>phnb2)qKg3-3Urc(lDcE@k%zV4V{b;e9?G!C)M|n;owqqsNk%D!KrjI z;Ymn)E@}xB37^(@Fb{J1l#@MKLEc%eUp&4&IFLE0*=47!UDIIj1k@NIkp@8g+j#Yl z_4JI4vB<@owrmZINp4eMCmqbWy@ceN82#ewyQe;rQ7dXtGH)g_CD=1i4R!P-^mTf) zXr?NfOg94_!@6&H53dQPKEvTZ$Jj^D-(HXR_jqr^%eh94J_njzWpztRSIz~zUTqiz zbY{6|DE`dYFUe*jo6Nc^NOyXM(Y{es?ca2fn_r9t?jq`!4Y(fxSYc5r>9_H8KIgnP zs4MHE_NuExvuGq2s6*k(uCI-B_Y0cGS5Rn`lPRjGBvMQvrXqAKK!% z{`ydM>e0q}_jZp4U64V+K}5L3oY+x)%=4F4hXPCuKewG9D5i?CcJ(S23)E%~9mdmF zyAq0~TmGewe`pY338EHQ(M6$=THZIPC4~8eD5h?Jil7g6R}>%!mohjtZmpGYv4jM} zl`*O*_cI$p4<71_4+q+h1z{Fr{1s&Itz+jGcfB`js|&UxMr*J$u z;~G~Z z@Z+AeZV#)!9vMgfpeV0i7rkm99!`QKGjoxsWkhOWO8!zZoKVU)h`@0nAqFIc_Ryd8 zk}=pf;iwF9DRp@>77LYyu$T!h@1&^Hl#V@`X)AgyP(P)pp|+pW7XxZ#F=4(eh_Md} zoOXNu!$n3`I97Oi*w{}gCXv-%RTD5VlYXJ&z4en~_{%-}^0vg*MP`o4oY>qPVx`@_ zF{Zm+`Chph)Tz2w1L|Z)dIf#l1bV*5G2Q#D;w=1dTOqb(X0IWLePT_OIKqS4W_|LX zUY*qiF0*~{&o9*A3^=XUZM2o8lyCK!^->LLdh4kB`)f-%Z{S0jr4;2zi}CW==AtZ! z!qY<5-qhz?2krq|bKeuiL+pm`59d8(EEZTkt5d44lt$y9DW_Jy`(&b4<`|$pGTj>< zf!TE1e$;CL&;4K=4>YI=&Ea@y-^YFs+j1BZLqL`2BFpW$fiP!#sS^%9%|p<9$zGw# z-lHE;ZHF7LrvHZiBi9+>-Vcq1!T%?m7A1em@Zx3Q9yl0^;I9kKhWakVZJApFtj7gm zX}QH34``9(q8MF44VUdLdbxYGMdHW+0J7-$J@U`&pwFh}{Ka&h`cpA#?1R@NGQdBg z)!)rIUg)zW?}t&>hF=-r@z42+W{d@DnDjO=nu}<Hg0X1FU&>xtQ+xv#KDKTfWk|=c(+`b=}@kVx20fJEinu0h%xBTVWAdzWE@dxs6q3 z8eWW}xL-)EuWn2e8C}M9Ou+f7w_Xw6>=}Z~(7AUsY`9-6N<$I9E1nAT$2NG2#AQ-=Qg3o*Cdi>Htz30%$#c zfac5bHP(!EAy?ZdbqbyDRx8x?3Y_pEG-IFU9vHhEwKtHSzhMS8fom3YZ_k{niH zEJIc#Z$GpA3;xBnt|ExUvqBeuanS!*glO&%6V2e?aX{$Szy@eW>lRpKTkoO1_@aaR zKItBa$G}Nf=>#|4BS<9C{;Tb|*I}drCSfo=F3Y_*!XKf(ETC4=Hm@lT}1WH=lUM0pFLNF-|sd?jALr>NW7 z0!?WYu!w4zF>vV5rugOh8G8}f=AMDlGNxr8mUsf2xz^qRA0Q_{^&U8 zvZPv4>>P&9ibxavn<9gJLyj%M;#uqhJ_pJHzt3jWyyUObY%^wkHOA721?ZxO*l zg#4hRt@j7HEa&aW$*hQk{iC$-n2%`}EtfIulw2a*JM>1QRh`bgUdZ%BoIEm_M{rxV zQMASLYkLJb;8zlKY^abz-ra(b3&3?la51cMvaSC;@Ro)U%||A)Q_-p=O=jSd_TYG4GR@5R z&4LS9g>um+T0XQ=IAQqD6IFbek1o(Ylg1M=Avf~h%KCE-;{yXHJC;^IS)ud++-PIX zMU~@L%6&Pnqegk1_hX7UGfDJ4`lg>=-l~H*p@h_y>;4LRLsVntIZE_};$kYhvHuyM z^42j_!f919O*d>tpzb1p0+s8X{@d&1~j!~Fz{fnPm7$fxYI+gwd_DQUuIiSvZwC`n<{I# zn{}1-;Wj~GQh%wpdR~68wje&)dFT zXCw;-aJD&4BA9$G7vQAiH7J~hRLX+bIQ~QPS6dnM{`36G135?eyZA7NYBF}okJzdU zCw8CKZ2Q#(oaol{gZ!2v7HO%liMTa#lVP#i3CAej79+UAT1g8C<+hTB+GSg*=w`Bp ztq-0&GdbQN?$mY$!0&kaDHd6-2O2RJWFD$J^OdN|YBV+GzVsPSu%QNZ*=*eDAhkS; zi))`}5{)_0<=v{wu=Hew~-+tsfr`FuP12^`zw_v~G-ExumyL*wj25$O!yn~zb zXtQWuGmsNvW8{doe(dzYX9GE~RuqQo30`t|sZ76Ql%!CswcB50Po8_Gcd`V&$Xc60IVh{;EF*4)cv6>7{{*qy9a{Xi`yvf{_y`iX%o-?URV2YjMgb!I_n z<3Yfz-oDV*2Ot#*ZCWU%ckCHGIH#&qqe1Q5=);a8?HR|*tjlDgdDM#t#rB9=zq~eq znPUTLGNaA0JlqnQnB7R%E656$DA=Oon!K#_{-_9~SHnK2yOr@`Q}!}BGXwt;YUvfO zB5B8hEqq3h3H*EFjOSHQk(AeAV`4)qCN1Sj4;PN5ux2NSbI85|`v*NXr4;#NKgo*+ z|F-vK){m%*1QJqK6JX&`OQ#h#uY_@VZyvhSd=6C|axZ)(`yDl7%abDrMf%VntA6(DbBWrq}N;m!g4|c65`p#}eF>Xi7D0V~)U#?ykf`U8e zsXbf~{6n1mY5yl6u*qMT{Nc;9e07ZFYP>hw13#Mz4ASlAs_vg+YycsjeC?#^-#r^w zg?NfLXda^5wke3JDtD7#AhbIXo-V*iC)2&b&;3t(r3Hy}My_Wp0r3;pgkuq8C=!7W zKB1`isYryIS?)bOCY?38F_8J4H|QmkwiQ4X6seY_r0x^rN1UMI9uY+WlI*R)+*T*v zu50jX>2H-waMg!x#6WG|?-qOLBfs88`1_X*-F_{Bw%^GZ*<69=u;Ls4mnH51{!C4_ z8)c7{D^J8c;5UhH@?wUW*h>nQr7j)fKa_>6``XO`Xi25pDvGUZler);8)AYh`m6Sy zt*Z0(uMbgmVh+=B(}c`RQa~%}aMA>Zz& zvqfY*+TCsSbX?5C^Wfx+KTmICFm(}mq7@ZmE}zrbA9gH$H>f$Cn&;HhW)|e;5n&I; z+y!ZbPiAemr)@7WQDo1Bvp^Ud>C4*bM=2xuux95m+FrW=oVFVh_RGNANE1>!Z~J&G zqexHj`AlLF?8lIr9xgRcy-oqMX>mBa^kHr04f|&`dqLx<$Ar3VYl~6<;ZJBJ8}Koq z=D(OXQ;)3BzJgX+XXn|EFgBF=QB^2NXwvB7$CH-JL&DdN%44;ScxAH;r7_vVom`+F zEP40ts@@Dv=khQ7Z#KNP@W~@=EpyjeBKWM^ z;Snpa75q$M$T*hS+n{NSV-j9mXq|p<#8tgxy3q*AOhu~a*-I2Zne!FD! z{#vZzJ{f-Xk*U$5MF@>MD3rTv<~+oF^yPd3G=n;Jn*IApchep_gW&dEsqv($m*J@0 zkbUQ^hTKWNz_TLL#stz|Wp&aX8ssbA`Ch-1ipn-q+&K(C|30{Nu#-y~s_Jh#I7&Ks z-no+ug8cGdwPkfI9Mh$JXQtNZQCGJ8O{%>7f_;x~4awWK0V=n;AIGvVZ>UZr1FBvI z#P;|0B^0;(KB#8$Y1ech1pNB67=-~rihTuB{Z$g^OS2gBI$yG}n=Vi^^_8{r2CvIw zMZ#JaF!`68&PYqLmo_##&(;nvc`E+LMsE=iFq5aMmMnzy#(5(_>#n2); ztmjYT3#d(1|3kAL;tqo9=UXwauU4~!VC~T>B|5>S1vwVEcbq`3$()LH3q=sWx#F7I zo3di(Ot14EpKNDdqI!DFKs~0M*8!*o#j>~F>Edxfef%ZF3?C3!{`_vFS4!3K^Op#U&u_VU^hI20v~c z@~n#nEP&|<3=5drh$oW$&vzfpVS8@;J*^#R1$&F158G64a#&>&^@B9KW&o-oRu_k^ z`*^$i{4+(m@S=u&@GQ^lO{?XX_;4%7LEF9{vyifl>bHEJTtEgC*DgnF=>o5zlC>@ z2MYQXH=$IC`O0^54y5 z`s+kJJ#15)Ofu?+Muj@8cPZfTKmQ^S*X{$7qT9Tq-r4ntpP`UeA19BX0 z!;}nsq~oleUXR#BGrpx&w0uOL&9Jz>h|ISWsQLC(M3eY$Aa#w0kcma5fG!G%$$f9X zND6Hx{}blvbzoFQ%a(6SK9+4LDkyM0IQ|FinOAUXYY#o}MI)Y}52^p<*$!xqoe=Pe zZ3BNKF5IKpZq1&4(TvD9Xl&+C^>*?x)J5L}RY;#3YlNORl~l}qthe@47~E5>Un4>r zWwfVzmH8|YEI+Q6pWFO>EipG<+JZ=w^caA@bt@J*+=BJ&GB7T|(;;{89D)05>M zN2Sn+G<8FY`&wp8j5Qze{f|4YDpKwuJ&g%|+7%xKzW;ES^}ohJV(Z=!TyFk}(!ZIF z3H4t{81_$B^}55UR0Z0MnVn#lP-Jz@5PchNf;QlRRn?mnTLmuow1u}T0R%QE)ev95 zz!Qdx^=6V3(nJ)7tv>eRqBtN7Q1lW8OLawko=qSyny3mU4H$dd(!h?xKyvt8A3HiWT=aX~Jqzo`eq7ewVo7kIeqk-wZyzpLLmS zz{Wssr)Ckmzw`}FtSb0jv{l+WS zTQ;TpsQO*64In&Okw><9V>PL&1hq5BMfMYpEDkgb(hn-dAM3I^dc)T<&vSs45@ks% zJmbw|F2rKn@k_N{y%*bBp6~ywy6*3mBzWpanDRRYt94mid!<4ay&nSBf2b=3(Wf>k-$Q*fQwFx$MeoHv9dGl4pSv#!Z1zd7Tn6U^ zJ^${vO@9b!hOZKTDW#*b(cAKw#$TTAQTjg>f8SM*n$pN0(jF67ukznHYxi(7@~F3H zK1(*^xeY-OWyQz~3r!{fB!2Gk%>d4v#FFTtPz2we?|BtPxPC1Qj_ywtRkgc7#`j%n zo{>)Ypm(K9wp@UQP<p9Z?Qws`r8l+%{M_U{5bxT ze({4ILbc%s39Z<>F|&Vvl2Ihv{n*-!DYX#!A>{^Q>usuOP;~M)XytzcKOI$A(BN|W zlyg}+S>Jvb-=&MY!1^cgz;q0m9v!?L5Sd~RMt6q&D1b16_bNq^gpbJqD z-O}2fGO6*iQ=jO!S30Iw#1ds+5`pDpUE?$Yu$(_j50O}Ft64UaBRGj!X?+x$G3rC}lp80x7&z4ajz()e!jaExXF zOVSz2SISls!E3Ttj|uHhlM zyGXBdo7d7O*P_uJ+$*eEc?)lXifSya(-ZN5+K94OfEEu|rdgR#*lGm;`0S8Do$pX$ zG(Q42)ha$7N$yo(VTb=d8ri^*0W=-21CVoE&%c$?T594`x4Z@0WNrfqJ_M3^2|mweB1T+iAVh6nlC zeGsRCKIho~eaMq_UW=E?gjFN`@|`P7xTupcyemp6q&I{jn@lkB$_hpYsO? z<;4PTW9LZUP;4U@^#3S2>#rsl?~j8BD5-+9gh)v<298idy1PSSbZ(>Z5fPB?*w{vQ zNy~@_6p`2ljBN-42C$%1O5xGx^L@U5!2RW(dtc}EKIfiu+rK`y&bbRB38O>ns`>LS zdZc-_nUOs1F39mCQjhU#(pKJ{at^-skm71JV0J%L-b-eR!~9}YjkT$KwnatFMsUio z_U)?s`Xh~4mT2;sPnW086`Rn5n#BjK)ix71cQHu=mkeyCBC##HMA{*+Hr7IA^zrfW zl+AMgymx77!t7+;zCtKOD<1mYI)DGxgQaaVNM5KefhU;{@(7-9z6q^E>ZfHu%0_%e z$hvn}#?p589@dY2GmKR2Vz0(@K^Gl{^%qQxUL`lp811p@;7(e90vo*@Ho@gCulRs|v)`AP!oi{fzu@`Kq5*J$b5xj`UQ9sgy#ug}ATITGU{!q^PDQ;(3FX z`L=z#R!M?a@J~1Ldt_UNbsk|Y0EpnDdeXd^Uz#7a_PXz}Dttf0e0YV=6Xk3j3QYvR z1G#7+H$;Pd6Vgf3Li%tLEs0P4lc|VyE5{vrZAQQYZmFe8FOK=$g24=C71TS|GZZmt zKwjZD&FxLq$go=yY7gsw4jigGPt87sxZJx?W5tV1%DTSE`Ou}@ zJxHdhsY}e)kJ+8}l=|Ypc_v=%NpzH^q0p?ENX6-JTLYOiqd%e)wFg+-y@W;q#M`@L zJ!;^qK1k|q91-bp=kBZ90Sx4p9K(1yE9WNOl52NfJBYu3vR}1_hJu;|M>{(oBN|uM z-v@+vzUF$VX~D4p@%Wxt26+A5sG)Puq#$>13VT4#iC1K+wz*G*JvG6W%PjpQBx03y z!>nntVR`|<){GU~>*mC02-IyX?~dXu~W(2dkqoM!r=JcS$ajtbwn zP@V>lcV-DCcjq_UiOfNToP|W-j3I7Br!IrBuc1lt5f(OXS5aJ7-N}oB0123LMt_}a z_sv8<)>8Rxp{)$8Xkrh2^KbAUO9bfyW!{g89~1tt>|9G(z10m>5L}n$9XY5JkdQWq z+I#Pc?WBvzjjh3tnyg1<*|UGQzeYK%TiJdE640ZLKruXa8}{qw?$wIT=WA??2P_08DzPEs?OGt z$Pj%Vru&ZF>}wnmRK4+~^~O*0W~k+RsAzYr#v1d2#K%5K{9X=Bl%8k>v`L&*aN2jr zLm*Ge0t*m>;%jGs#qB!Hd=>lE zh5HKqkA!Wsjs;UYi|+66&N|5Z-fmRsJ@yqiYPOp93IeG(Ujg~vsC{N-C70FPrU#~m zsksfu_TM{}5`QnBv?5F1s${BOxcj<|E5eHJHXlAmwKX8)twY}*{^cy@_Mv-!?3?l^ zGS(>U4=u%SVt3F*$1YWgv2AB6=&ohMva^^fyN~6Rv%5Gy>T|xn2hcaeGD%Wj;Fb$J z0~aZ<#L7#HTWY!xZAZ>1o(f_2HF}Pq$*5y^+g;~h*6Hy1W#g+?mzY{peM%|iI16`s zaJ+Vx@t~o2zXRp3It8JR(IS0_p~b|o+K$ugMmE2&7HB@oq$nxx9iw}7vyv_6{l8!9hZlG->(n%BFO# znZHv)If`9HkV(x%0lWL+bzll;L8s#9GRepKyC|*h&`{A?4ez}?E(^1KH+Xi)7ejA2ieE~8}@8T?lSn;-v^ZMe${k0n#+B!T8KXP5ttv}a*}g0 z+nY!FjPbFHG~BxA+V3Q(2m)ZY~<=1)mO6H=V$isI*d6EAFCcNDnuALsqVYn--2d;Ji6Gww*H+dmu7ozVVDYE`I{^@kl z%ihf+Chp=3(s8up)H<-+<~eM9H{}^O?>c{?OQ{vG`DY5NASL4A;GvPFWJxp}-v*=e zESMf4SM-@r?nn8}-nMab(R?}c4tF?1>S(^FWi#ZgaBvehNIJ9@sjUAsORlk8B1PHe z&CR?;U5j#C-(}&zLsNG^1wz7n!}3HMU_KjK3?5<{qYAUpIq#rPI(W!gwsl<*=6zt@ z3hz5{o{y5&bTc_sDhy_x^a=_BXH`b@beiH@!_;EB3P`Cz)E`eh@RyGaX<8-_wFF=B zw)GF)Ju|T;pOxM`XCXd#S_!X~KMjqd!{=o+V>>_HWDHB{l+I)^Vt${Y-}2;oXTH54 z=rs|KfH<(-&GgMgVFhNfXsD;n2lMx;_U4&v3)%`Pm(My`!%W`ah2T9>$BK z@Q#L9QUycYR}TN7CdK$*$tOjx03&1K@DgSehT{bQ`3SbpgX39C;#@$4%A z40_xRacF*3oU+zM8(EadRT!89PKotxjTH%G= zh$UAi+P2gzNPdpz9emN$4N$u8+yw>SZF6YRN`LjkF2R*-fr*&RRZod#SgX zA_s!eQaJv+94InL>)P7(eUv9Bc+?VnhtlWq-WWLuFq4Yo021Dq_7WviVja z^p_8S^80neL=!D4CWWvsK8M(MC(A%oKCT0nS<#N$(%%=fm(Rbi8m20AgBr+n*!jwa zIEh7pnHLh1sq#tCt!zJKY>V7@HN6Y!c*wuoP1)D?e?UABj+Gu9Hy$>rgrTGp*F62b zu9B;JEz_h5)@|4}!?(n10oVs?Kbt@!iPhm>4t?Yq<6ICqE?}MfgIHMaQgpSItMQMOI{hgTx_jn6k_OJ4CT_&ozEx;o1Ib4i*y2$&s;+E_ArJI0tMWMk6 zG834jAQJbrpnYkc(HZ|-vokw{r*yKvJ!zgGFjeaO(nTHdpg>4&uE@xv99(D)5Avnt z0o2d~!INLqtL-6TgKa&IF3?g&cdT(?y8sCk9n&rXD%9&2DJt2 zWL4m5OCI)f?c_n^ZVH;z(vXbfl&k9#r83LDO{~*MaW=I|p_WPwiu%#BlipUZq;l?6 zLTE`&`@1P?HYic=+f>AzgRR5{a^d|=pwDZ~3LnlRzYVvlx)McTs6*|SuFolR$lM4Yw5T?dTL^{b5WwsI>O4($%RU0{MyZJjVb z8A_7r+xk}FIQt;Dyp)e!Q*ciGc7X=fG)se&FLQ$RdFZy)t9r0M+U34zzgCMk3mfN9 zyD7`6qm1IUfTQGou4aG+*pXqQE}opPxguSSe!QSOCM|hg5k>H3|Z#7flwt>)_MC~T^g#xZc$8NjgV61{Pj4ico@s!%49zzWv9xAU^%DHep;hY@HwM_!7`}O{w)mE|tuA z^b0)Bz?6AFQy|60H$BWf!TuZ95{iF8Vv&KdJ{LpU2nlgQce1bJM8Y^Ztc7^Nt0~3hhD$@ zTXoUyM-gRl>L@1_XknxGxL-kJ%Mhxwk~1~nAgz8iI$Utz;z)3-i}PW1d)c!)py0k= z3XABk{P!0PweV2vGHykx`#^5V*v71Qs&3q=pS@jYl1oq{$~iJ}z^WMB@1!Sl)yZ;$ zoON)TpLvrbT7Xo?DU&5v|F9!vTg#X)zv4x{C?I%I#s)X$SnWplrlW&JnjuZsBh{p$ zIdNu-R|@~c3@*q&5YP@TGV4Ohgw1#^JC-j$&jh&xQ7E4r8(ILes_xhoml5%@I| zx%Bv7wMR9#ey+rhu!iAa@#5nZke6|;;)hw5u&$fg|*iJ#u?H> zgE*nUsF0`ORap9=W-}lpK5fc6{*@Q=9iA`3M_X-0u8p(x>sWLbA)WwHw_ z!-ES50BM!_e)T;Z)0Xi^aD*#0o9HbJC>m2OYNZ`#Fo^>8u8a0n_0x*i_WrrMR|!iA z%H7DWlS?UlGGL;DOG11Q%+&4j#m?)X@6g+;-zj=id~@pYNGlh(Qk891(aazWkz6C- z#bMdke}u03`s^qdJn)=hT`=iu80ijw+VhbnCoLHYZbAG47xB`s znr87pDM?YXngKO4+Qhj9zCxj6EdzCOZ6ml>Xs8U&-)!%-;#Rd3`a{dQIMFT;XAHFFD90QB*s%|~H}bW{OZAh@ zdD}^b?Aek&m=X{J8S0F)nNzZuQKm!b`lk)fS$UOb>!LQLbFZgq|GEn7nDTN&eW1(+)ZiFVQC|`By z6u7ru5S+JInTg9abeF3v1Y(0e2Auomn~SFnXrxVVThb;V>7~XirIO4j-BvkwBL1w- za#um97quFpGLKVPSnsNpU3;d9F@ysFuX6KO1Q+y~`_4Q1*q%vA=Sb=~0~_IM9giCX z;SqcoY+lvCU4p=!hld@I>%}3>XO(i{@0uqn-JI9@&I62Zi}8E?t{*H|lg@SrUg`o<75sb4EWqd>0SzjndJ3>pQeIBbOxv5L}&vr$KJmG+8Ve?0+w zkUu3^G{Aw+3+-Lbqx_E{;>t@lzUjkJ!?w#DzFv6x;Kr(k135Q^Xw3v|>krU0klT_{MTXi`3SEq@u|_T-f7MBeq5+`ine?s2_cI?t~DpGII`tQdHPUKBu^ zHo}@KsHLHb`M~<)s`Ki5KmHqD^qyEVZY)hNF}bqjC5L(GQYPr1Bi z{{VxQUxAb0^!nNESSzozSx{^{R0f}2fGf4djEF6_**R*e6D8o2tLj)Sa2@xLytz< zvMmThj3gXfH>q@MB54*>&VIxj49w60+Cya~kg{Ih@zLxi77uWM* zX5)NZEz||JSHB@Xo_U)nPWHZyh~1rLGFw=2krG58B6r{DR#r$Pp$?zG@a*H#2koq_vFtO_|X z^T?ChP4yO?mBZ%v;bdc2y#VRd!Qe9ENcKqFaK%(A05*Tma z36CWmYJ@I|NEpUMs0M>ngdc;bX^I+Y1%VhY&u4*T<0xs&fm(1_v|v|wL~u!Byq{Zl zcxLRO_V{!2adF>t;eihxLS;gm?56$_21-LdJk$hkOsoq?xgh*f<9`f>2#MMMF}T$g zFG0!e32CyColG|Zb#LKr0Y~ML94)oE0aI@?cYXguZ}arU6osPNW>H(ObHrN-)Vg;9 z{qY4|{w$H-0kmpGTh=T^RA||iB(@%Spu~@InuB6B$9V-@BUS(Z@4F}n^UTwV^XM9j z(#v#ALnh0%tgSR#tsZyw^*sV!dWrHP*mtt4PDh8;c*)g?-Is^QR7lMq_GTh_V6=bA zkw@=Cw9X8RU~$(n_KU&=$G-itDE(^lbM}o4{p!yN^CLjAA}dDg^N&2_l3OtdMd0Vz z47}s9>F4L_MC4Mp>NgHjWYm`7aGz?^k-xfJb<>EgRY21Ll0-H{kiBHUm3DP*fxC~8 z#nV5{{3rfomm>Tbj5AODVV@EB)@LWz*yztpzwhKCxy<=Q)uSx~KC3d;KF;%jpHKg zo_KQTwQmEvCA8VJ)U1cSCPEt7Rl51q4!w#AW7So^bfaVb_+1&vOT$qHiEZFh$`b>R zSI5yl&S398a1=frB2l!kThBgZ~2jT#Bc4cklX36-9wnBR@{%*^u@3U(D|vb z+8>&N8#9sJ;Mlo_fr#*dZZG~B{%vkT|Ek4_n6YL%N`297O2MhW>ffjSl(0b$Bwko0 z_aw?Oad9>EVaM)BX9j5|R?5GTRV%W%!>ID6b$oIjJ^R|qD7&f-YM+1CX)cA3cerUq zNYTr=Q~JxEo|(u(+F6B_gV6g{t@xwW1($jK9Rrr-6$ytKfo zLf5;lQNX^{D4;LEiOSthseK1&9D#4Bw2Meg{aa@DQGi5j6zTnLp{(halevu2pZ$Rf z3!Vv5&={EPOlq}!b{?5`W8R~dG4FL-=z;W;IVMa?W;%8+P04_Z=gc}tRRZNxix8=NUX5!ij+llkNIr%=iJBG)+ylk&gPFOrvA}#{i)#hF|~k+q2(?zI>8r4C@f)$^h)wHL-mt z`%h;ia%!qOO1g^mz|6G7`rsgz!4k?(huX)gX7wUp;RX9PQ5Fq;p!8X%FH`wjyuh*m zDE(EXz5!=Xu}aB9Gj&@Ywrc?l6Ftwt9ND?7i#3{ulp4EoOD(%irQ-@ERgtY$y1YtD z*wq8AMJEoDYK7JQa(kA1MDOvuy z!wyZGku4{9qY-kv+kfcHMYOEdwmqc!ZGH%|*S2^{x(DkJr?B0l^~ z&coX#5>{a#dH1{s?1p<>Y9F%XmwoX67+iHwtETAijI4h`bOedg$k}MsE-&Uyf0tSO zg5T*qv|MC6t2ET^+PDbu=~MvowIolao>w9Kl2o~vdPLg?3W``bnWZy0%uBvVHm|txk*;2(7Y{!W z8f^cwTJ%$rL*QLcfhjhb-8QDL0nWf0?gc$^HeUo?^ljus6TEQd{ zW6)#>Cq_hPjC)mvq@(!%arNH6pr|AlB}kbzaD0iT@fF!#wa7tzytJwamCJ`p73}>J zsJ0`I4J*$x-5S&^TSChKn9}cf=J}0wd7bV3ZQ3hSRa<{%ubq!FH#* zIitGX?8niX7I_)-VeNl6*rklP)TlrlPH!)~^$2zM(Y+OVn$cIfE1VQisXaDXD1WXqj-FjxLG;g4SwhsH1)Id%VAiMQhYNd zztzL2GGhM$?hX=XAuacZp>OP0(1S9eo??M{i@EcP+{>5%=L=s+qF;ftx=qRWRJ}^Tc@a5q`1sUM@IQKO5JuiE-%eMddPtm3!37x2&QfS}X!%T(p%<`am>Ffd zT}p58czN8N2h(h|;F)QR#o|Har~xc+bf_aqa@1zmP(+Z12Y0Q_&Z3!@|7}v^&4n~? z#d7l`5ng9Xf6t-tkuM#8RGfuGx%_dz%izHy*uk~;Xq-fjsY^@0NfDBieKklz@lUQ7 z*eCX0=z|BB2QIxECj(8KoyCCfL9=eR$d{mCH5Wlyg?Hcmo0jf}MY#4nm>Ez>2zXff z%NSF=d2GG=416jI*~snH^08tU_vbqMB$?IlaZ&BbsCR|dM9|ypiHA>zMK*#)M<~+h zFdm5+v##e5s^-R@MHdcZjxV^+p6|$KL9vwHWfb(dVQ!P%QHys{P`Ea`2;_FaXYrNZ zw(-il(jdh@Rq0f*6AF>mw9uP=Q*+|-cPlSLk6zB2uUK4Z9X<6GKj&~p0bq`f~iP`;e z{p~NLx#Z=U*TW#A7CV`VF@tY3BktaI-M{wHMMTQ)yQm*kV%!OW8XSG#Cq}|oYqlB$ z$ulkDl-N?wId=0wQ1W4vWq{9Z%XzQ+6g4i1;UqbDNz3CcSYpvh=GJ@Uh5Fc1qSZ-I z<%2nN57+75zx$gU5y-H3IWU)o8{MLUp!N9ubW8L$F4M$Mc^YbGpO1#>tRYlaFaK?F zz%Q<9E}5Mvv^5t4ZwMDzX0unri(tSAoiuNcwSd%=#|hZ;53~UWCyOm zZu$eqy`;=P|Jz@5VuoO3!lJKuB$Y}?jFXA>e3hB4rwq0NQ0oRrgjU;*`3;fL;&U20 zmIq|J-{A~s%*z(jA2`;$-yI37JnOz5BtDC2TK;2p(H;v1)?N^z?$sZ4%vu>n9)#KA zGW919$i5W#$0aN3NIN)k{fic@b@Fnw-t9WlF?D<2BQOoNex;7cp&B^B3iquv@kpN1bRlXQ%$4lLdFjttuiuQ)ub3 z8+>DTq?F;!HNL^vFjYN$Yj@gw<4hY#g5s6P3Ko61fYV}vi+f3u`M4C!E~FFy1NLF@#(gJn?KIE2@^$PPktC5hNe z{^fHse8qLu_QYu#0+j}^+;pTe0^WrsvBb_Y_>EW}pU9igWZY*4o<9G)Xkv$>kKQP^ zwBin3T~5CCAUfFeqH{PW)ni<3?5-L0?stD4xc%YStan9bWzvkLtxfgUneZdKe_ONy zE!Q?I0$@SiDHx(|!)(YS6h1bIk5^Y~vPE!CRcHksea0;?HSgEkm0Uf#stQ_RiwR;1 z(Zm%9Z`v#_z#-D3(3#eR&(Ri|wb7b-C$2OOVS5-di2N3Ypu?JjKC%rTksF@j>L>|`;Yj{maT&+6jIx2!Bn($Y;Tld(ijT1tJ zNm~Iwo-qO65rVImtNGHkH6ho*1B4N=(A2x%*JJE(mG8z4m-2gx1YZX^Sf7_^w6zaO z09||2Lm!9~9<||vl`T4r23x>xLwYqJfdQRUTdiS;KuKv)7(P<c0Ry&9@$hMpRk1f28;s$69|9z8StgMSEUyH-wNb13`tCx zQ4DuBTkGCSfH+P{txJ{)u{);BQBtTiYQMj)FL!tR1T4*zj5G)`@SZLUZE=r{j3rnG`5$s(0M}teNDOuF44|0;r-M9F?g)K<&%7?Q>1fT z!-1eZn2PT-E?7?`Cio|HLRrOQr+}SvhiWMN#Ny$lD~(%w_Y~XnQ0_7=_0}$+b9|*o zjd!kNGFEz^N7jmcIq!|W);?TrQ6vKth(^G7=S81dUIN2D5(>S5U82?dKz}g6X_hne z&a%G*G0v7W+dGEM=}(&@k(8xRC-QPuLjalT(9 zB(co_(ei*@6F`F(c`nkb0R667&v43y?m}>b&uIJP1J*@-hzGWS z@E}uCYQ;zi{%UStS+z1FBjdmscuGt3!X0P?JA;WjxvQWg6ZP_<&DhdUfXkD!&fuFD z;E6Z_jas;J1 z9E-SMm^-gm2$HjK0A8a28fGOrix75Mf7JQXqv$Xyx;@prbx^qq_xg5lg{avD0jtF2 z1I$HoQ_VR;RqktXN`XVkwT=RC>=UI}*2;<)&F-ohpVP2)sW+;TVX&x`p61iT&A>z+ zTokO#-V8o+O|#9^df#kgDs)@Zyc;5e4vNX4n#}!=!Dy>PNG+ODr{2(pT}#=`r~e7` z9s2%#BDC_}f5mno=Abrq)C@DB$L$f&bBGl*sSxsClt)#Bfd#Kj|2W30FPbm9zjYm{ zTX9UHt>wD(T@x9u{{TH|aBru|L%`l0cSK}PW&ss(9#?-Kas7-F-m0Rjq8w-sXZZ0& zcvB94i$8pWcA~XN?94%A3|FZ8sunm7qKq=ZE7ie_s=Vw1etJdM^{*F@?yR{zrUrbc z=nQu(hrhi)0&gE5`foQm>yal_EQzI&K`qZ+B3%}IY0rO&8GWCLU3H)Ek^hkb7(-6{ zeUy6ZEGI_!t@z@-u?zq1!7hJf&_sVF1El&o0iw0Fwvc*vBi3pu5cwIty7e^ugTe+j zx4Jq=>Fq>CqKYa}H1K!>Fpl3XS?h?dZjP@HjU>MQ;u(NQ)&-g!PZ#n7V=}ck*SCJc zdOum8e(2`{bjcu0A(n2~3@ci*(wQ!#c%hfV?+D7cdc_5Hdtn`8!-!QHq^rZ?Ti-QI z+k592GeUg#!WAp2nnCD9BKD&<3(jm!CATLEGxC zKPcnaOIJNytIEgSV|Qc%$=+~8!8LO`E8R8vmoxhw5l$7ecR0w)cv1{Tn4SucP9#ASi+BdQ&K`Lzz569`Ex4S8%#YAzV32_nYV2RIe35?NyKT z(3-eU3FIDrP-kfLySe}nppGY<-$QS9$ZURU&syfY`3Zu?m*{v3RqFU7#7hl@MN%iF z;Vy$2vAPj_;Q|o5{KuL4Z$?J2HtK;&&m2^hv|n!KT)|f_A)-Irw4B;O$5vj`u|JF= zjd9T}I(cn&g5s;pCoiiwxbLG*dmc;}S}_lT9VkoqImrBPcg3hJSj?d{CCc$~H5_EqRjWC2va#nmw?Vy` zLVU2hHJmO)QX>B)@f^P*Gv7f#~XkH)AL||IXGzEDGO? z#GUwh9uJFbg9zh$^nJ~)AV86bHO)(ahEIYd;MElN9hDOKBsBgh96e-l!@KO%ecjC-IQkikM~qaz7vG^QLibd?-O9gGCICyGC*AF6{NF|gD_Vr# z`{RQaw)WKyMMGiEVvehTSl#D9b;>vKM5GQ&e+j5%NzS9m0qu;h+K_!yY3DhJ5sfr> z=@+G0HmX_wi%D+dM^oJ=$3fZC7Deovg`|P(k#I$RD4gZh0|oWyo1HDl;u6Z9UacXq zYVszcGTohz*;PX!$to&UHW5VjN7WREqztyc=>&{)5?0%|Y}I}x$9R(CALnr# zG#j%hW@q$}A9-?{Q5v#V&Z~3taELjMP03>US}Rs9t9MhyT`n*tnVidZis?K1(d^Qj z8TW*(qui(co9IKvFh2XYn2Z6I7>mxmjW&R*H8Ii#{Y8K-dk*Z<415;E8+5Zhu6X)0 zrE}wberS#gm!2(POjsrzTl}ud8T@xxQ$SQ(h`S6W>>k8zIoy!mB)!WSupf&pFxL%` z7t<=Qs$ge4;{hxGi;Gkq{Y*V}X+44%COoh~}YKoao=idm%+*nW z|28fYUH*4?t?D{vLVWk!(2^;zD~!y3cQAcPBOzc@e(~-*pQ3TA(*ezP-8=Pg%=fa{ zSFsx`WOGo1)<|iZWG&|{ern1Eikh|JJ}HqqtfgJ@-ODG)<0ErHhpu#2F>Z64nz9n% zuWB7VRH(Z3F}bPcy%sU7$)dEm3~(2_DK|e%pc-61p&lIkbf=@}FIhleGiL9Jsd>f@ zb1^E$usmj4{2B@*zsfinrvq% zySf^LzbvBiZG*0OZy@A3J|wQ^wCv}QNz6Si=me{XfO_x(msRGgIA&w)*Jg|*_K(sO zFJf2cv5K9(!9~-DuM%G@sTg7>?uz4uRcIbK+k_#qeCMd!=%j>&6s8w2bno{nP}hRe z+lHi_l93w{d#G7_Q$d>HT(u*PT&|f%jokhC_>FyDAS0~U>7xS6kTlre3e?)0T@hK+ zGC9X2K3`y1OK z9R~5G%vICA3F&+}%a6;D`XDaK!c>073$B}@p?AuX!d_CU+5Z2)_%cZ*Ak;;A2yZc? z^t5H7XD`lJ?`Vq3hjCEa@p@gyR28hzh=*YM6Dp}PKNdEzQHD0YPca%Vq%P2}mD-Wb zEJ=cNi%0;Z^2V*dNhWR2$^l$6r%{bQ(n?ubnu4MuY;)W0Ykk&szdr}D(p=a!hb>+R$z4>C9!+7`(xjH~U?9GB0!bBlV{If1&R%V<=CW+7D>%k+-EL2o; zdz^B*wp8BZlS*o_gL9=`Y$sIvqrt-H9CHjWwK6$8B$$h)LiMnr_(j@NDq{F5~!wInoVD9O4t)&(s%Dv-*!D1irGs4?Q_w#>#2 zptfhHTdpf~U5}5BT3fx_E+*PuPE`{07NEz3!K-u;0X7;nt{j_&uxEU}fpvFBe2HNOxjW4gXZq3* zS7Mku`Pt;G6uG&Sc78Qb*eOJTd`kX)6lXb8VzfrFW>kerg3rBy>|mRQwhRMPk7P-S zpQ%-y@(5vG94$#SMAPsk+LIV%yQi8XQ4PsF(+d>7*1abW(9{T$-_~%VEAH*vUNCZX zFd4LE7-t$A>ASD-YCQ|#y@_*R_el99r(KNCL8*5?fr4`d0KI)mvk>`Wxjz$sJyTdA zPxOz)8Z#Tg9B_rtzT{`N$nNvZjqQnKKbgC#_@0>*)C?a`i2ydZo16&m*Mv&pFKvvX ztft$+z2>og;4J@C^|`({D_4BBUq|U^Zom<3!OP?Jv zHs$0grpWFF-eM|x%a?5^eTscSJb<_)zMKI#PTv;U+Vez{A;poI@>s9y^%o1{>LOVx z3Y*{pfTHy~c3t+8*ELJvPFew=AEVi&oc&_OUAqqEG!uhj3AA?Omha+jSx!3tX{sZ% zHJLCAHfOYyR}pY?Cy!+U-LDjnVWkH}w<>4t-aZJ^7e7A5TyNXi`(`do08y2T29+1n zAi{PNo7`PujaXsp_s%Y&NtmeSA*M3s{L@vy)vCASzyrM802c4}muTpT92I|Aa=fGS z-7CBdunb2$>_(CM-KNEKYPwgcc~q^i?Cs?}`ku!5q6r~YsbfbckEb~(22p*3(&t?r zqzAFtzW!=tdmS)7+&kQOQ9d>CEFeNP8|O3I6lZWH*GdzX9jK+Pb;-Qm*RmJ zWUt=?=9Q>Mvs5gwr{#hW-6nK4PtxSb29cgJ#lAE1B7cub99+=lD$s3^;*1B-V4L`6!{_|ZsJh;vg({r#&q@kSjlP?U%hCk>kNNFT z`U6HbAkR<~@nGG*LhXv3fCfWAUE8C(od;&G6BPf}-_nS=Hf|ikfh`EV^o`JM)yFz^ zG5D$_m=omNZr_8fU_?zlKj21|H-muhTv%WY^bWLWxn-{;Oa}Nc)WdDBZy_!=)G9|d zTO>rohhL$f;m53szrh~eVOwW(qw52QZJR@!aQ$ECVbXFii@U#jB93J%Iv4c5657sjrj}OEeusua1{Sd^AMRY^fsPg5Y1vuNj@J8J5;|)HAG1a2x1m!e! zc`GQAvwcDh{e-rznxxuy%zabG=$M6J8%WUo=(dpj?47^9X^jHztwIfsY74IcN+&)D$e0PU zX;!niFO)mqY)(}Q<{RTx6ih`d$ln8t`4xA31_Rmw#tW*na5Vw z%3-NhZ5`HfQZcEUFP_`CJnmHya|)jt1YFrm5Y6vNZ@I$0pj{+XxTl!g(cS-+NUkph zv%^;~;|w>}`u$vUa|1GESoS`_6onYn2Nm=ct&(QW_G2Y$Pw zfnP=n_pnWcG2GolRd4Q3B|ui?N@xp20>8GG+?d6j!UcBQnhhSCqVHj{2N8~tfFHJm7UvhLkj|1t@If`=-}*M|jZlcX zpw;APs7qYU;zLgwhn~esXS$NW>?Mh7`r_+*J$iT{wAsMv0=~5V5^`&WUM%W*W6>%+ z85X{H_kvp}sMZayCS&kx5s=!hP%wLhtCTVl@h#;)k*U)^O-9ts3`vDS}$|68Y!C8=UN6{Sn}2PqN% zfxVSj00W^=53UyhPRJnX?u_)*!Kr448{03pxFXI7$le0q6Jg6cUG$G}{M{EZSZ@LN z_XyfYdYAtKiM~$hvuMTy6V(=*Td*SADj<`}<^jzOE8Tpi2c)GBk|D=pwts|d-&>o# zh1N*wa>JzNUQmD^dB5_#s;QPDP0@lTa+&vAG>-yGGib%&;uB@J6e-G_AS6iDmq zpDL^lD53If`wnqdQ-cj7?UTpJ9dey3j^SDGFE}3|6|0@Fx^OC88?~_niYrxZejXXE z6#3Ki&95!6vwQW(1K`z$m(Q;*8fr9iA6=s#Oy(AZmX*I`Sk`3lsBfmGneYvwwJ|Z_ zm3CldHblcxUpWrh>olkkIo|rqwtAeO%NHLItb)1M37zX5!(t|`+_;H>z{1!0#mmZz zreE9op8NGfnjue4Mdis+PEXRCZ4>)O;F~P|?$MMM)rM?IgY_VmpWVX#H!M7fLI>G1 zQiy>_mn8F1lJ1iRzNM0wUf%T)j6*`&|50q-|5P~MAFmY2Dr8fVm3dtk*GhzJB3sG0 z*BZ0gfpYQwo7o77rKfGSg*W>XzJheDV zu2mZQ3Y+@xiP5n0@*zzT_rJ&j0ZD?&yJyskLFYDDfq8*uzbr@R4Ad$+<`D9)cY$eKaIwhK&c;6AL%w^K#i5e zjx3C_>Lh#v5@Td_XlDj`4epxskVS4Px3pJ|;PncBTKs(8kh*+Y2v!*_a>c)gN+zOr z3yhA~lzoCZ>OE%#tpODS4G3u}4=|>7b4Pr~aYR2X?2|=CX>`}4lL&!Z^9<$SowB8c zE8;33kq+(7OXFij5=4YOzx&YgNP@n(UfWD6y$`~Z1&oUuYlnl#wI9%J4f7sB&QDR* z5sg7s+F=r+bo`OKPb|+QXK0KdF&cwCc){v$a6=8mS%4s3sTXEnx4<*%88K=p>8EbS~a^1~}W0C!W8$V#aB zQh(L?5wW)7rFt=nw}Ym{;0Nn-WvLnBB3BcIO4;%?9HIpE&|fE$j1YBvUtSAkf8%x$ z-$96mC;U1`{n8H&xcP%q!CCXp!tf6Zg{5aVVwVTo;Dy7~nzk91i;9#F7yQ!m`?pM* zauVJLY%IT6(S4ue)(VkggY$~gSfRveZxI!2YLwmHqlc9yN8CQjI{)~ej)%+`z*yX5 z*Zej>EnJ>sVwsEdl6lV3s*24o!-&Cmuf6W9U)IHIzNrf=XVWIX zv|s4i>$d#B`Nd=Ex3-P+59_T5f=K+3(&1xJgwewkCs!ANzIIVpdtrO94HgY+!h@$< zs%!8Q;9QKtsOI$Ko)L!1RCwh%zI)xQR;TE87iOl#@sEhB+2bI{9vC!h<^LF7hz;$g zKB@BqY92C(@runW3xDnC9G_gz(FvvNkaRm-X9E^=SL!nsXw)<&+8%5CMYod;4=rsp!ej;f zXnk*hq&wU*iF$CyFLD#|GG}9%l68<_f9*BPy$*vxBAueKW3Z_S%vZO-EEKwb^@)Xl z5NYjuP~``8a>3~Z+#!UVvwSV)G_w=KDFnklF|>6dH~lR@~xE9LQyZ%@)0qSmG0&SV6)D_6Z|l(UWc z8Ah#JxcP>*VtF{VdR#8_iP?Nl>(^D!7ZYqN6eY=@##B|mNvla3D{>SYJ|X5;Z|Bx1}qq zM8W$kc}foTzAPh4DFA-UUYsY;lonFy1?tuWQ~kbJ+CY>^pqsnzJT}A-{4s2Wu>mnx zJY^gy?_Z(oIcAH5@8%0`a+Q%uzR7K^zs!5_(ytB0fvKD(q%IIihLQQ79c{8Ic&K@> zWTSbMGWL^lhY6BL8i@|4KI0{T3{4BD{>Qr>Okw3k(lKxTV60ULhhW>QI+R=f!*z}G z&RT`_iygu%eJyv#;$fl42|z^MhIN4qn0jF_D#Ckio-C|=xpH;giXHhy{U5RuH-^Te zy9P3u)Z!%^sY`vN;P>nX0eB#7cwr@lqPPJ8XkAga+iz=jD$v#=rCZUr<6V`pC7Wrv zr+R>#Yae&n-Viz#vE9peKRIYi><}X^Hg0!lmnr)7`h7D3|6{Cnu-@TDT9VAeYMMb# zY69fbuOdd~?Jl#&!NjI**fdqI$K?K&-)$_EtluyaJ1+JdKlnA@Uz@kcrnU3o>CY%$ zruKEU$`z(C_6e|?1jrW7u0q4u#_yqbH7JvqAaKE(AVFtNoggZ#W6p6_X23n8V%+%`F zCn-rH@RWC&S4qUW#JT}+G4BB(+@^dHD=cpwal?Upaf_M; zExErod%J75S3a3>Qr`D`{ogrV*$32x`c`@>+%L9%9e8SO+5&@Ff93S7)xilWzQT>5 zUo&lw4u$I@y4ZW97*X2r-mDp`2;$qDpD{`k;7lt)L%AQvnUNgI@yY5oIZw|%+Xi1= zh=8f!uJUMEV*`D^QIxX({f@)z+GoIfQT0sK-)vI;+x>g>j^*@(t%pO3eavS!ztM4t z;`2+0P~xY3V!H<8Ym7g8{iSmgSHY2h*S^qVdQ%3N(*O6<*VL4t#8ci0FRy8FHJ3D_Eu@~lTb2WXrOFF8C$bgU7WlvIVMi8 z4K{@eJ9u8!#!}O}@K7(jH3vhB^*Zsm(lkUaiB-_oY3np^*jqMD_x5ky=a?v1%*1GKW!7b*fM9*M7uX@WFkZ}dRPTx7?gpq#JImDC^{UG&Zrgj< zI}R_?sDO0Fp0Uy<02`fFIL;k%>9to^()bgwlucwrT68U3_JaaE5E)4PPB|=1QOpeB z&|W2GntPxS0@1_GVskD}uGMF6#ls_a9y@iVZ(&6`$oRmh#jlL60`?vVT(dq<_0jyc z)hmRB_)bO38+hbu;H{je$7OpiW3IreUVnefmpJ*v|1Wa1Me2Qa|DhihTZeEtKH9zU zNZF?ozZVN1Dc&Rt&5C3~yK+vq`raPVeFIx^IG8-Rb;Cj9j1%-;rJe}G`&ms~YS`E_ z^+7^lOd|F1ep7R$mTS>RimOCIRIhJYcVXh8Y_~=3H=M)3 zp3$%^=Q=vzW#OR*XwDy&xgYNgcJkXMqaNn`xxB`Q zQOL`HSG()-!%c(w`@WTY_tBW#VjfwA>J~19r`*RO6V~{k*3Q9_b;-talu6w-VuWcbr=1DJi4s~NVCkP+ zbL_ms`H*(t^X>RG2NQQYL{%uE{~+b}VTpP@9iSkR|0V2}6u;#5{hJ1n9~mW8^h8Wh z1e#d?{<3nw3BS^vxc{9KX@E@bdmAGecL_J@H#l-FGDVJpQRo%ZWVn(tHPr2GV%(QN zD`ehWbVlTK+>dri4W~>2hD_7xaa*RXTRlv_HP{k@z0cIUgJkrKE)SoU>CA}KP(s6>--9JF;4}VbF_AmH86$_49l+1+@}PCV8sV|NAMCO*VW_QPEdZ=LRT-XNOhc&Jmq&@O{F2Ef73KjeJZ z7BtQ>7Js;GIrv+aRs9tvyc$b;oRGGjB)?R~SN^Rbz?aJyZj7!m z!h741=Z+<=bs$6SQgbj?FV!Ny=ZK73Im%mp2$;FXX*V#uG76AxEbqzz>1ONdbWd4A z=j@op>v!lDWbbpZ;pE`V92a}N&ceYv@#zMaMou#N`U>A42n+8VsT8(qUB&v~XXMkeA=if?i zaW>#iI$uCVmOlnRQ8CW49;;1$rbI~0J2R)3T2o*PKf1a;T*D2Hv^P96!E4`+I#(7m zTAu{S5v}H8f79vElJ~Z9I(>rh-Ny*;SI#51WhfNkGJ{DRUINulp3$Yh)Z)tj@)0{q z))X?mv^jDxNsQe<5B;nedP>!O^n`XjPTQ(~@eyVj}u}P!8kwBVe{8WM>y>JP$!Xnh3o&|n_mo?~m(bv4>+8iauMO%t7mA`1<85!yesB|jBH12U(PnY-H#R0Aq3 z5mUYRQJSD*qjnkXaK5Kew&znlO|3ZDFY>WA_z@wcp|`Z!eoHJXH!yWVa$I{}3j=FP z)yU&k`RdR|IIDmunUos?-^NEvTdbEyG50SUwr}@)U7*3MozoW9Ru7Vu*_16axsqtE zs8oB_3!FJGOd|{x6xge!87ZoZJx;AaxukKgCgJM?8e>LAMBGeg|7O)z7yqc+``)EM;XcU>~1hoq|}%YExWaSWU5|>6r!61l8%DfQBD(M_P(%4Z`M?X2Uf{!;o8qXlAcd6!VW$%jkZ8h$%i@3EI( zIia|8q@QMAJb3{xFWegW8@Lp-;W-(WXKTA%PBm#qjaf??g$(J#Q}jq`)zCZe*0X^% zl_K3Nu26SS6=%YSI~#}h&isQISuu@(W1_}dlJNJo%UMO*^Ki_+%QIqy6sJPn^*^L% zrc=9z&};fgvCfgdB%54QA*fSZcm2lWwvgyAV=)}LvE=h#KLTw^5N-r^fZU-NVYV^lv5IKAf-OUr^_xAWfX%{e|3H^osIfyL2S8clNO_9W7h z$;7U01RoUDR%Ahbd8<34xu&;NF}&nz*)cqBUaWa8Sd-j{s~pnjAnu)mNw#;_6}j~t z>@F}0BqQmqACU;l_2e_MdZTWRq5o%>$gJu0T!F`vnCR6PsBOj2RxOzfKaWe49$;n0 z*f^MlDoEi3P1lZrsVTVX&9UbwzA`J#8A}9jRm7Ass>{ZJaW-*rW!_xk7MgmA@%6+T z9oJGaRnD8}&$(V;)X!}#31YANVZXb<2Grv^&I6Ghvn~wq`iBWt#N7bD;7vV7=iz5E z+~u>oW(@YjStMuiGOAd4kXt#je>dQv=?h;OtnqvE1`DRsp@=|J^?eZs^H?~*K1PT& zWaC2jRLQQG=B4_3a!4JZp2?k?eyZD&s1;tOj8AevVJ4#eOoU=UuL9l)_yq;tay;ll zW7!n2C7F})li$x{E?@N2G7q)C)k8g2z|hKA(52R5;!{sUAjj-A{0hpUCZ(G?`E8}A zd=@Llx-WD*TO6%eSI&Pm?LVlBy@s-9D1^*>$V;=j{e9e{w7JKOV(j*Ii~3`F0fwGg z#3qKoMZS7+QvOCrc;S(7z-vzakw%o!#)TRkxkJ1#Z#ii~jG6s9WE}EbaKu>Pci@H3 zF!=rOmz|$v6kg#h50Y|^Uu|)DbS)W}i_XL(T>m)V;O(k%ek3GrqVz|_kWNLk4a;Ce zZRp$-wYzM-XYQQ06IFt-Q{Uo$J>!J>i2%Cp#sFCQC={?SI70%2v|CJq1L%9tQelX?aF` zRf=i2)bv21fYp!ljE7`V0na;S^6149A2G%DiQ1Fil4HUc(Y+qlsmI2rO#NDXyK38% zgndjIU0BD@<%UQ|#@5rV49-Y}k7O|Gwlt5D-O)!<%i92M&3bhRb_py$J}%TK=5zJk z%@)EzcB>LK!tslqgP!&if_eAq*yN!JCN>6Y8Z*vFe~;SDPGkX6j&e}ss$d{SGFO$~ zI<&AaqRvzPA{(CC(#dUwh|p>{E;63;Vizy&y9Z&9@&z_4mujWBr_dfZgz8eT6V95` z?=E|Vl?7$wB<%t%Uidx8m(Y0=BtXHIGoz$vq^r~_>tV@mvqG-NK7UKmlkXLl@BK}K6q z1?|+Qn(7F9tbx*`!C4Idz+Gc54oq(uqBmp)@-y}dL-Y}j>Retd)OBUrNz=XX+Tag` z>$@HLVaHwC6@2m%V=1kl#SE?i>NqSHcKjYD+*ZA$QF^Lt)z&h7xz9ePvVtYm;%-jl z4O?V62clow_ra~~QeI)$u{FOZ(^IXW_4RIZ;q+) zmCA${T(z1&;-FC>ZSuUKiTcPBB=K%xDmv#sHMvuZYx90~@6C8-BNY_LK54(#=kadG@&15GWi4x2;alo%?9MIDE61^75SZ%!0b=e}PV;?Z3@n zzY0e0(qvJ}FK3yOx!^P(-A~5W6HP}ezGzQaHZr|9XRTs2Alp9skUwn8{v~ z&ZFX232;n)i;C9hSnm6%Bu4AP4K7c8*S&FfgF`jviQB=ap^{3<$6yk2YfIDdRnQbVig_OfbMXObx86M&t0rp z*BZ;;QkIRJWsyCj{jkTarpyTUZBlsD6-zcgtQ`ICTrjMg46a_@0pssCYDz~B{8EhV zAm57a`npj{1)#rXeKI@Ua)x$TyfbP9zh9Tu^1*~gjDLJ+lOeNABe!yULNph*2x&7i^Q5Ie>Q>^jCzc2rcR_~aXpZalcp4-NP_I=Npu#e~5p{0_ z_b6wf#uR-}`tQLEX+~71wx)6tc`?+f@1_gB7}5>tXQeHtLWgb-1(e51h@!Cd~Uk+rm0s}#$(61>7{xGA3rH^%s?i&J`j9KM06&8a7WR= zb`KmaCrpk<55QJYlq@5sB!4Nq8*i4Qr*nzuEN7{15aOdX!~4;nRyMxa8Pde14b{ow z)6XU^cpzJ5^y^jb&NqD-$zgmIzR zitT+Q$5f%cB;$N;6ZmzDGmU~FMncWqR%@PfFoAE|fN9KCeUmwxt}~IQvVk#kDam6y zij&kXh0!=w?+fN+FJ_#9$|&S|V8cI>TX93_1(2W5lcwtCvv}WkjnFca9xeoz#1BTp zJiZoiew8^)fM}BKcb{mg_g?-n$bt|u#n}@Cw*WbMpr+o%k|o1o3}HOB#NUm^*{8;@ zG#X{#xn+S9+cg)N1Xs?oLT(C6kDcEv3VF9=dFY(w^)mt+QFp3E^4J#ELo*2yNCu;{ zN7XS&=4`uC_z5a>QV^u__|tyvb3&b;;@eRdHiE-o1gfZ{_h8GwN9Ywyl$Z*)_D#!I z=Z4)Gyz?)!uyJ>)ts*?F7ny-Om|7InICk6X8TkO%4y|x~s_&w_yS#F_dzM>5D;io7 z;j9jcRpLhLdfBPp)l9tW~z#uiOK1D zczDN`q@R%nBQCLiRj&GWZgVDvx-t32^wFqLs}j1To(AU~5A^aCaXfnG8PKH_2(W); znTe)_ZA7+B`&Prg!5_g2!b1unWB{JL^GVRc5d_UH-*nPdXvKQR%aZ@f%mT9m{*6^vy1p zJ(d?CA?EF{cXFyr8Amidr-*7@Z@ueE74*1wY+T!l1ypZjOU7M;vuDb?c2}=iuUvMO zWyacltavMIR%G?m7)!a-vu3d6lC8;kZK^(?(agK&k^;sdZ}eEtXv@eM{2G`~(vTXj znUs$8UxsZNTa&o!o(qGQc-P=<7RjdO;fzX&XzHiKUapA7i2uZH=U$po!&#uAF#q5^ zN^rpd9iO4%yyv^4r-Bdw$WG*GeaIzyfG;hCg!oKYeb*K>;Qp!s1P#iDsZdqMaa$cO z)JN+are8l-au&rxr(*L$A8$u4{z{&A@m92Yii7Jcxz9eqI)O9#<&eXkn1y45O^Ph? zOGMcb?XH1~ifW}`^N7v#M$Pz7Tx@U4O#sSc2Uy%yK-J)!S^(8#DSlNx?nki($t3jY z;ubO!@0^aDxMk1}S$4Z7!S7gUP6V#@WX;~vPC?r_Gk71P!-DxjV+*p7^pA_9(Rp#&q_&{eoT>DnS9ViXoox28y(8^vg&mvKRQ#K8;T7oZ z>Zz&nFCd}wAfTE6!k^%_ThVq7q;NI+&AIdDa|!FWS1e?I=35%L4hOzTTRT{GHfkE< zA50h5Bs+9oZTb=$o2|PpT3ONjQF8RrUJo!Md$jU_p{$e$t-h5n_-4Ye!D0_(xbK=v z{q>*u{Z_#MnS1^!n(S{~W?X^LjLekRYe^Rw#h(2@nFyWoRm)0CMm^W=4cG7aj^oP2 z_jA{G>#P3w1U|aM2tfDH@3%q>`5c53NIUlSKD#>#xcRBKh}8y|a?l?^mW)?QyA_w= z?{O1pjE?VxMAsFw2>#T!J_RCi{($4BJalS1zBOp;Ub z!!NnNzGPycP0ueJDNV@GhZID0R*Tx1xT0d+#f5`zd!Z+3f0tyc?yV~a&IK?5RYj`sc(~>^8~Rm4K;>9r zS9i~eP?aMT1A0GkM^KJ@#udIUR29glR&)vcU^S}JenQ`6l4 zox7{46Y?&Yeh5^E!L)k);gN(s}V9E8w3weed<4hL|z5{g(4|DYNu zG6kSbRiH~#>{<5~D@cI+fB;SLYcy^sE7i5ZJJ+`OzE$xOs|-k}rgf^@0Vt(Y$&!ld zbo@GHaCzRqHUT%1n0Q)D33QD`y5D-G>Ck&|HBKR&O2i7s19_HS1NIHa`b^Hj*?9tW zWOH2gih(-#z~BeLmQ~GHcHUTgK|MlpG&}P>^}bCC^^bF%erGQE3WXOC@ozvMn63C< z-E^i$y6=Q~-@Pku$%hiUWfbsid64P9E3IZgpEdSMlZQgh-Qy0Wm2+EDq%f8YZyUGV zBfQ}Me+nW@!K($@{&)!0RnQTXwDs_S{9x@})p>Ltg+p5WziUb-+PXzaU)8A|0%|Mx z!NW?yK;|;=i?!D_u+@&d^EXHMVc^$4LLba{C-9%$aOg38of^(;CiJkE@VBzfRTBOT4^J*JQ7alMa*AQet=y#*IS$}kvf7(EV+m9E@Y?xW~W_skn* ztP0gXbZ;&w;5wPot~{0Us5&KA`UY10iJb6jWYJT9w!Bjdka)XaV6Y|bCpIwEfC_2+ zxb%z&jEC1!u7(m97IZy@V7Uw#hiCVgt9y<`PJ$TRMC8sqcUYxv5{q9j%i}H6s(0); zbp^yOnIj54aetXCr59CuFJDEYtr)7;Ab+B_hDdcRJ3kyk zVuFlaij^z5TkseAu)TcU2fYb=?Mva|Gva#SoZXp({* ze^FpIK6`2sGb1cA`?ZcED*()ar`Z5jo?ICf!*qFmc_D&(1lfSSdqA(f3Y3L|NCQTc z(PrC8sn=J0!X69qQqHAmsw1-wovkG;AvLG)L2q5`K4Mg!rT1uD|Bz-me`)# zr0_(Lg=VuaB5aZqMe5M49Mt>tAUuiUlyC9&hk#q)V)Am!?$p_%F1mvJBuXAEkLKKhLS%&;J*b))i@!0Dz0HRhn3dy3Sd-pQYqfruK zTazTf?3~3)H{dRno(_+di51yv?$`E@Yr8#hSN3o8#^BtNkWf2+2L7|mamsVnn7kkAfOQv3~9yFs14_%4(*$Txz1z2qw0W+xk zGx06P)JBTp=qesC%D&@0E{RzQzfn+$mNREJ@ZNB1 zgX@4y@`}KP*Cwye0(LVi#8>Vwn}FOGbWN3p+rpjzD)>iGdlrxgac8(0R7UBfUHOU) zc6(hx-O_B+g9aCHO7w5Bjm^W@I$iy|pY%p*F?npUGcz#(;v=z~8$F{lQrxy57&h2K z%foPPj&5I#YeA1gYiZ*z z(IPW4#kS=U{y{|RAPXTh7T>qURuE)_y`6PKhIF|52U9TNq383D1e?{iB6{CgX~LxI zW{bICT|m0G3wpTS`0?~90f^lYtM%6HC{&u@fcq#HGhJ3O`w8o)|D4j)KUt2>VyGotMaz0@K(~S7g)`>*z6;sTh_*8RR&brZpaLG*iA+4*JqJKXL=|mQi}utPBrM1;?E-2Hh*W zok)Qd%CEc0{disqciSlwvYy?EF|NoJ$8Glub?&_QMUO~ zC=PI-fpW%&m{coUo;q*EJsaoCBfA!=V4V`S!Jm%F2hKpefT7s=ZXqYd|M1yQn_od% z$$ul$hg34&XA~AJNTq%< z8*!cz8yDfGiO-HKx9H&ZvySFwBl9A{ZE)N+1MDq{XSIwgjuF?LHf~rfTVlBQzvj+h z-{&A@*3>RuPjQTTxOHv3r0QA?G{VmbU}?W=*AYu?sX9%CH~&fj0w-P*#%O0Lw4EIp zMxvn6(mWIvrC?JoQ4ROo1Ns(ZPzLN@jf@7mCarHCJ@0LOCgOzutl=5`mU`IwBh-mc zT|4BHi&1YLLoC)oH^I};efgoY7(GT{Oo)wdF=;EJ^-x0)ihIvE$c;UUYRB#>muTo$ z0UkuQN>UY4ykjDh-l)$9%YGjdy>cmg+3hW#7B!AU+YVL}I7~iaSRIqK%V)QB-v^p` z-`aYKBx}ss0`fX1p_tw{!3z6Kix5^&>B)b}I}x)$Akn`>5Vb+YGg8{+M9?fB`}evX z^1}nB>dKv-A7XlScAsnzFQ%hd%QzLrO9+|cyDfF!1hpEkomt-bw~5$Y(pC(osy!hf zU|a2Ni{GT_FjmPk{|O^BU~2wIMI!l3aQLWEj|~hB_V2zYsWd3{XQ!>Li;l1-#6gn%jJHr3LTAQZ?x3ZnU0TnU!O6Ql>VF->ZSY1}d4A}D zqC;2reHLIp0TWfS?@zXxY;vD9)x4g8Sq`ETu8pRm$|zom>Ngw^Vjm7BHmv1$!wwo> zz}eCpc!EAXXprZ!1F=Ym%4dYsSq;BRvD3>1f#e(0Eoq%waGTXw@Oi-ff`<(r<)o z+0h0eAYX=B@vJ?e#!mq8h-Re9+DAwA%{`dx>T|M|VtrqT&R+idio>UsdbHB8-EK7O z9YfZ(*vxC*?^Zw*=uAJ#y^za#i;;3a!inMxb!sa-%GwVf=_QLVE^6|n?y8&TJ zGE$8L@cijcMw$f-zx?DiC-hASe5hHuEo!AnK?Fc-Ybc&65eYQwfv*T`#qpJIYYjd| z({p}pbgu#@&|R&%KNQj1gYL7l#7X?+Fcg9`k0wnu;DK+VE}=(l3f;rwoo^U_lNm;; zWr=}i49A42u+`&y3)*rMDg<*ht^TQmtP=t!p3VOIBa2w_G2{KkZ5x7LBQ~z3fq>S zieFvcd-;VNjPD54Q@~3adEBu6fT@KhOF|j2ns)0ibgzMhJ>^NYAJ((+GUi>a`qsyDac$NjTsEJ6xR+qsl3Ty zrI8i-SZYn|^UX@*eaO8RLMz*9ks{_k>QLMINkdmVZ9nlrm;yxDE7oD)dYt?&RQk%j z2Mo@D96+%2CT@`|qjr(-4=}4#!|%$9cw~DFkIh~ayq-%nS-Of_=)xN6FO7Y(!ZdKuflo28i{@W%PIWN zbObnm&ShuST5NWQntXbaH)S$Y79`9H6>ur)i|B{!o0KL_gu@>3#DWk;uVr`*|nq_A_0~cp(A;G2=xJ%db$}C) zycE*Wlk5QG9j`3QR#%pbiVTrri}yIav#V%55bEUMZhW4Vz4nXyDkJb=X5yn3>5bk9 zO~S)1+0!4??Pg{AAGd(FHk-GQrw{k0+=-{i1Kd%dsT^_`=?4~!relIgzy%t-V#xyv zZAi+Frhe?)V)GLY;F|5YGH1+VLfEE|IqE9&)rQRvO2s%}pzW5Pd8dpu`62G(?Z=pk z?YfnJc9)f_#j@4+2e4=A>kM`rq=u!m(9<)aM>&A^`2M!1Bc= z1ii$t%ExoEs(D90D&GvRQfOt&jFf#J8kPIWSZ{CP$|eEhl~!g}#Wji~8nmxyRxjr@ z#f7GJS(KvEm%a5g?ceT({YMsio}3~tn?$F^E>1D8v#NR#X#97=)nM+D4pOoXKv@x* z2ISb5KgYA)0`Q(t%OA#SD0+<&;t|jdS9Ue{!oT5iU5hR9m0W9KvSgbNQ?t4o29j)x z3p#i@5x_KfssnQ2sz$rda;n{}o|${Blh)VWGAcxP+yCOYgclei;(Lp@f1Y?fSnR%W z#f2+Q*_Pd!uPy#$WZ0%@fvVbyDdUVOz(2&SLxjVyjE3;W0|B$%nxkXM7p)nl<& z0B&-Zl$SpQ#LeoP{mMXKJ6w93f(ARxF1(3b_9Q?XayRk2O>O@>XZXp?$l+EeK_TR5 zRc0iY@uSRhU>felth{;|c6|j7e1CJOFqULn|pBWv7HM=H+jDps_4OX%N=f|5v*w$Q5SGZsJ@Px zf>dS%0BbYt9zd-Fc6gcC-3vO?CyUR7C&7hd>C~a=yXTF8Y0u;8x5{_G%Gm|M-P=>j zJ(26haN`{O&E&|N7S*~iEdjP|qZdkz$K)nQO?<7YzJ09HKuAKu#%l8RE{A%-^I?}n zs>iQ$a?oa+}sk_q^zhn5(M8aE@(^+ z1^+hm;32qtrKg@gC25A3{7!lklE3vjyij82$%%iEFaFJz9#(TK^Gk0YVNw6^-qy_* z|Mm<~La?hz6nf#{qc!gt3rW(kK4ErbTUxNfG}&dZ7ZPfHi6-+3hKdA}>ytd*W?co3 zgT6Fi_T&5Uw72?99M$iW;d~c`;<*wa$hd3Xcr#p2CFEHkzGit#?Zh$?FjsnJ(l zwmHsikEj=>yR*)l{bJ$0A!ii$|2Fc;yy)_f+gMVdgN_F~GdE`EzftbfyB35Bcq1a6 zF||-4_Ao#twfO`$O=!_ln%Vg40~^nHF;(yQ(!h&Nlf~6;*{;5_Bs$F16!fSbq9npv zJpS}tW~fQ=$WB2pG~#(UEIM3R{cg?4-WRj3NOU0@zt3&A5|?WGREDDL$eYQz%+KG# zw7U+_Y|=@`MB2T`fd<#BVLr>$2-}P{ngk|rUoX5_`%HKs&xIy`-&(vmNlsIYaSP&m zdGjUBTa`t-X>$qiV`|FUM)~VM^&O??67gAX`^oqTe$cbR>P~i&gkMd5X^VYW=p&am zMvLBpDYKDD6--_#8OAvmIe^-2*K~cs)c;4rTI$M#l}c)Znup^VTR!~yxCPcvq=YO@ z4Kz`Hj-4UiuCr`?)rI!}SEt$o-iWV$n3HE;YpE$drHtd2%m(9C(%zm>G^I@C#b}bu zShScfu=Yzd3ayj(YU@UM%KC;!Xw10&3IOZW1C6Mum~5~I_qi?K|B| z-IeAy=u z*~08~x4sV}rzJt{Bv*axBr=%>s@_ssN{Rv0!_~H63vpY7T3k}@psY#E^ug|{^1m)T zijAogRxH;K4oa7Qc=$(J+*zRd-qe}}&^u;KcJ7UdH(Ghy>ANU(QM`$1Q{{tOB;=dQ=lkZ3CrMYCi zM6P5wQ-p86g_B(x73UA8W%iak?K~RZ5adsd%PsU9rio(MJH7Zzo*3BLU!$6=S6J*u#=ktMtSc9=2J2Gscx3s3_>PfHf4gd6*%+NSV?wEVW4U2Q3?>dM$3H zlScFak36-ia3Qq{ctnit}~50+e}zZ4X`=r z7>i~Xp`i|CIJ9_Uyx6}yj%oh-V^EvE%QAQlL4^2aE;(D9Yg5&#o{O7&XE3^?x7yBe zd=RbQT1s}QsV|*@<;N<2ml_}SY}%s3x+BLuWqf6xn{RiTC(1k5dZEnC^Yb>fs}|Ij*`lVjf;&m#p{}1Luy35|1 z-0Rmql$y{vmFLaxMvryUZ!9s;NH)R64l)i`y+h?O4RpC&rvdVFE%p;Y@io}zZmen> zS9QCu4sBntkU4=1gZp^+?>t{D&@#*nJGFA+L_3@yF{^H)GcvW%X)*&_NOv7i$TIm ztwtj$t?1AxCg!oIiqlEit|dJf)ex{&8=IVFh;VtFv~wVbS?t#<5F0*{W+kvOqbEfd zwkZ`gTe%ZThK>NER*rLnDT#&L?9r&kDVHVZU7cZ(Txpq`3|b7u;(*0_ zbzE6Ih#^UQ%<6iBopwr{7CR7v=UfS_@KYvr2PahHIB*0h(mRyAG>h z=Hpsy9wjP3THKqHpw18Uqr~~nMk;jyVIQL^H$D2gWJEe z^vV#s>gl%ql?bXilszWw@Aw+VW!<7F3Hk#@;P4$*~Rq{uVE(_unsy>}yU!GXg zcVy8X9LcTWkaN#l&C1+b)T7^BY2Kwdu^nYTQU3r&r}^NsmALcfc1t;@S`RGqQEoZ( zg2PplTD{A|9kgzTy*kE0&UZJHt!zJA$)0KB%&X218TK`M-@k1;&rhkTrL&d!0gijs z-r7>@PIc1U`TFbGZ*h*A;k^y5XDtWO?)pofV|h8^394?6W@OCQ4CgHLx>9R-%-)_i zruCJ$ZBBR=GViN=&UqT6>v@24&bnp2^dPr96Qgyc)1tE==Q?s0;Z5FXUz?)*sdWvu zBYgzYpKiL)_G3az!jAPN>X?}l>SIh*w$vjSvb-L7VMs({#%8y$=BPUje zQHi|cnz)g1u%LyGsm$E33~xjZYcYF6oZ)gIjF#GayWLZq&?$0-8q*TOv8;Uj2;XLC9ZuM4J2|F5iO45mF7?GLc zhJ;mQ21`>RDBH5RXlSM;PKoAf7sjo2l{&_)mmSWIXIa=3&RMR5C~D2Zj-pUJ(a^?< z8iO_~jfCurXq*__Vwh1z#`6%Y8TWeuWN_rmu-v$mKbJ2F{F#joOs0?h_D0TCS6ZYlQF_q&qU%>vCp7owPG5 zTd_WL6l~vbC8YCG&LVm0ys+m@x3e44`JPtvZ&A*dW~mNwo$o9&Th#_rxk}weCuaQj z9%*pC53pmV4osVSB^yF&51kqh$2|92)q|Kzl*20d%xSIGdTE}z4>0Cc=aW(TZ9X_phDD6G-+AXfrmlg{ zJ{QhCi;U27#)dsvUxm&L_tCaLO)=M?^PbzzZS=b6WuaX12PyZN-h7XaY5MfvZIfmA zv!Slkd6Col66eBS*6*DA41`t6*G!`ZQ+5iXv0RRC70<$ol;rq^= zvsFKoR+`0gtA^nI?4il0(L2mX!SryXf456J#8_OanzSEN>fmw00bgs zf#-}+9a!|p1)d(mHP|s9TLEk*mDtff{4NYc*|TBrDP??rT-KCPCQ$2=)gxe9!-0is83cIuO6cIC1mK&HcUXE{22 zKUW+8#Y-McgKZGYaZD}dueXC?`)qAz}%gwb`g;*ac+ao!{#!)&@VDqHVHA zX>A7uKp8hQdFZQ4{xl{_@P7IK02I2xX1-e%QBT_(e&<0=hO17zpMOMmqM3Z*WdtxR z;Ny9Bq7D%8j8Vm8Mj4dCpuGW}H>Fx~QolUKb86&?Y!Q=C`FnO$Kq|#Do%?FCnb8MP z7Hn9NG+r0rvnXlGJOMJ<`r)yn6m}(QLZ@OLr?x>!&I<6 zwY47kp)Fly+%mfe44k3{yp&C-20p_pD=AwyD%3nugk;$I>~Z5TRid+I*Vm9|P;xdr zNv2=FH1h{3up2z4(Qd_^9OT=sep7KMZe6CMqb&O@G{WcO^*w5+b>6jRt!F%=aCiRz zA;Nlku~q5#&QbXywkB+}_h>B3#&c7$u=b5eZOyW>`_%33BF}5H2_YEB4s|@S0cY|R zKFb#1MMiQn&prlUWQi$klB;J58RVla1OQbSZfvTr;)_0L(QrX)TWjfcNk9ut*0Q@M zP!`J`F&$m~$;+d3pVdhsNDu&%Im?Wqv*jo7^RS?cVinIcIp8UXqIu*MxoTxp12ka1 z9*aIFn+eWM3N`k!9XjofF%Y@aJ~!X5_O(~6dt?)nvD{1IajJ1h%d=CkeS|K(dakUn zvf|UvF5G6j8)9s#vEAjpM*)FZmLqNwGrp@#>;iHnQ1|LT#zlXgwHU9b6SES^9A>lt z6pz zU)uWBxlj|MDurhx4sbiFuf}|;7`a7O8PqOG*ef1cm4wn@V0g@Wl*L+6ozH0Ua{Wrr zR299a!5xZAt`NK;CPr)2Y%yOYqxcYLppo09qU)6Cf>sZgqAmyO-Mg>@i13=$S81JZ zr$R@OILgz(+0xM9xH!j<2h^y_C(%(t&+NiIGyE@Oi$J;lafUeIs;pSE-@$k1wg#f|up86Y5q2J-Sd;B-<8RvL`v$?L_T{ zyk$KXJ)EgLq$gEsr#7WogIK<6uSK&O;{9`1%dYOC)Zg(%a@x*ub;@U%49VL#dE=F# zr~ST5#YyctIKh6?*Qps2T+Lld$F?}(C)LE)m1iZ4o0+FH>)&CdxD(~(0Gg*(1mdX1 zMpml*rWejgF`6wT)T-q+KHja@tEHD&aZ{J4+ZBodF1Q=WzcjbV#8rn zPw^&`+M{%}Rl9)PIB93}EVS*E_<27WStvhlHa!comQ8i*n;QIL&9b6u+e^g#AF2Xr z%BoI2%G&EZpGUzZe6Ro~6vol>#n(Pt6l3fanyOZcrw+yGXQ&QxC<+No!h^z zS^3ZX{=G{MhM=EDIQJlV_Ay1_$vMwcjRQ=WX)_LK=ba0dnN^${6?(G;W$@SbohEb2 z8#4a@hI(bc7d>~9?W<~hv>HBp6hWVn-aVUa(WxSH=brtYuB(%%;d+&lj)bZS)8>}! zAv<-Kp6;j#nlXUMJC))@pSFhcUXrY=g*+%wAoOmV>UPi zdoCjSf-opd?wm%b3p+M;LZ|DFpe^_)$Bd`JpT+_Utv))H0R}q;&F2U|V6{7ell+pR z)ADCFeOvesKYA2Kci_!X4c+Bjw%ZkAPEk8zvBd4#-{b?tx~_HDdTN(t z<-03-vxUiypdy@k&#zF8=7S$#^4yR>g?73T_~sR8L1LsTwy6G_Z|9T0rbPoan~eA5 zLSsSoliu)O6ybn_qoUK%4*l>wQ`|FT#WSy_bZlt$hN_}$n z`*&KGXOio+8QFkeUIaG3ncCuSwNp+fu`RuJmUG5L22Q{T(D5>=ytz`GBF{Bn`Y{I^ zQ?pN49NSivR=MU`6gY0?)<7oQ&dcf0jz(=)Q(2wN zz;~o)6?L+zm6#;~dd>GYdA^Z-fnnzQ2>`S5Z6LRk}@; zde66Qb4jmo8Q2VYmK~2~_{D;`+0m}Ob@fQc=i0&h)~D0WI5aHIO42G@Dyq&M(sJqJ zFzP~_bK=!iX6n6ce!k9`tjcl>16(eDqjn)D85(^#8eB=6Tg|Cf zji*8-TRY7e>}?kr>qz4fY`uKjh7OBLWac|kGb7fq&)7;eVcRyp974Xi&b=`r!0aX( z6+MM>u~qJKsN?IzY`$>YX`OBHR)^at0l_c`>@%fOoyko&mlWk}N>>!|l~(fABef*2 zlaZz^Q8Acjf{j^|#T2GOtg7T1#%H%hCxuzX)fFZx^#c_N%DS#h(l|O*c1O;=%?mT3 z)Z{br@+88WRy0{qlQEA51oiASh@l|Xr<~>6BQe9wsrYo*EHk^3Q1MACAG_f_M!TrT z*!ybO@oNgIphH3ib|*C^I9dvgjb=uEsu8;4w>6Yi^MD($DpZ`G`FZwLK+RY(sOJJ6 zy$a-?j9MHyOLYp)aXw2o4DBF9Z^YH9v;jXkgRyb1foXfl)5QFRB^KS-y3^ayD#=Cdd>ZUCiKQMN(Lorjdn1Jh>{NmfL?@_A zRr6WEPgCf`lUC+>Y^-hg>YO^Ypwj$uCcf>w44`)wKaMG#P_EPmX&y4XqaI7`J8+B% zx_8dsQ?=El%gK)o*?9P3t@TpfmV__M<3tqM)H2PEg+AQCay;B%ZZMTATe6Lcnm@;O zw{n=y<=eC7wzqfviR)^i;g0uJFWVUWqK0y_Rq{-L9-e&UVg_;NhG_Vy(SQR!o&9F3 z`%B#}3R|h7vaLTiwu3vhi)+!JUrXXJ=%g_SwBiP@JFEIMiwmCx*{?Zby=N9SjK5lF zc@5a&&=Vg%WwFw`Og0&ps?&5TY#P>&9=P@R?2ctN1kDZ-NoFA+!nnP2yihA(9(JXN zZGSpN(~Mah^BgKK7E&t8eCZzXvbKIb7+XXl^4r_@X+ZtMR5)%3~3uTg4$te5$A>xF8#Ib-w)6jK{fR}A?- z%`uaK+oHQ<*-&dLJnOQg!98==rZvT;!<_t;$|sw5iiKo{eB9tyso_r!&c&{Nl2$og zf|>4k{q#(2)GPl0BRp-|3|jY3aW?X8q}$Nxi9Rt`j6L#w*?V-#SkyFJyivk}^jRwf zl|akED>`rpZ|BvO5CFV(Gor2`4OZi}!u)H@bqI4|C>LCoM+!%(qNDb8`BOkLKjOWS zR)C`yYH$kmJ-aApZX_MJ{{Z=_fhf?^Dar>@&ld`u0?SWYi1c8*Pe}@oWLZIu5GjLb zNsIC><(hLtHGhv^vAUBQH0eT*M^-to?s7HZHfha15qw#(=6TeC>V%xJXU=(7K$%#U zNFuEE8DBh}nP|3o9DCtCIBY;k9AyF#`4m;j9+lJK z(TrJUg-F_Ri$+BNzBdhxA2xckGyVRhuwgb8RhILr zbv8b6;;;ak(Q=eNVOovm@nSPyU5fyt87b@8&R%qRl<0xJT}fTZ@Yax3Wj$JFHW#i+ zpAA{KEAbDU?L3N+jX8|i)EO;SRG23n z0BE7{+=97?S87OiLUF24MSk6SXHK?LKF%b|{;W#(r2-z|fn}M$bjIabVg_wUxmlv& zPF%Seu8%=QJ*qh|kvP0etM(>9uHLZf^E1e&S;@#O{a$W`dmhZam==6lq?K$&Jd{(q zm9>N$cLjjF3XpMHwlgt*BCTt|E#} zy7KB5B#hbBMo;`+gR~WnAXOfU19dLwJm(JCH0sQLV-Uug;5`;fv}MX|FAuW0+;vT) zo?CD;X#PQ_-;Hf+X3MP3_QI^E{fqgd6xDoaqq@nZjP7yb3w)ga0Q3~}ZL+yKmp$As zv-kaux%(ekY;m8oods~3wrQ9Qr{(lS{{ZBqa{mCF;~}_v>Fld209MEh=^*$3?Xl?8 zZt8lsMN}&=7+aB@NiqRez^gBBG~te{4N27~&8_r0<#UGTWsAwe<%cg9>aVfc0*1<{ zMK<)y1TBroXs0i9WIE9|Xnr!PHZ}SMR^y6xiNcD<%ohR4NP;IWtugR=scWt(dMze$ z66ZX4r2*~b+4Q7wqGaEf+(d1zfy93!RSQ z4A`?XD^EbOY;i?1sK}Dk??qi^<#uSJEB06Wt(*Y-wki(MFf~ zaFP;jfEOtdK_DeFAkhSY-@aLZmlSMa@T3;9Kdk;MtJ8*cgF=f*?5W6xIj6|4lJ?o{ zsYtP-BtBX|Vnn_%uU2u#RvE6~EW1q8pF!6PslumbbGswEl6GaTA=fC_}Mgu#i#9Nhk|C_Uxzxwx~|RyLJ!F0X-}@Z?MDF3Led|@H-x* zoa47e`397F6!S**4&J;g?`FT|88Lq;t+1v&f=IShm1#AGN%Lanc?N39soOgbAXhVAUMo1$8_Y0I-`3SZ>~2N@o6 zzxVe&SCNGWU3eg-%aZ2o3RcY4KvP~{8#7k7MkqeGOxcAO_0e6Yv9GWtuD4dLJ1nG3 z*m0XsZmPvq8?*SW5KUsP%tuCJ(TcaI2@)~7jODnUIW=}>J-I|ZkJ~*P)AC5hXkE^L zpkFd^mDe@s!xej_YgEMKq3dOsGNTZ2z7jGmJ!P01UDc^xa%maIppZAGeg!*E?B6gRJmXdO0-bQnOVcO(jv10 zS8gWLDB~g3ak>QR0aovn{{Uy@44aXz;AC#xt7Y4a)^eq``sWYewEn~L234c8HoDPO zYui7kDi2;?C(Uj8=@Ye3!(4i242|K~e!Uo?fPAF0^BhT7;~JF<(R+6R(keNoF>cc! zV^n(8mltIBw<(-kyu$bM5t~P* zemPFU?dsku-Q2k2CeP>G5y2U+evN7_Edk5KHhTSOIjSej)Ub9=!+=TN-NA0|-{@Nj$yQ#%un&w8TdeluX4>z?@PCXck8|%?ZJCpGEXiE7R;A$$)or(}aq2zWrLnCcSb+81?0(It`TAdEfnX{Ks zO0ujCc#3U35>xM$NTyLq3XkS$*y@ ztG-uY2J>oV6;)T;GQhK&@h zm{FPd%EWfRDT_`^6~j5ZZ0exJfdabyu+76TWY2qb4EQ@@*Q;p$OrZY&kk-7}64)o# z7K|Is=$fAk=FM7FWj%Fz&sa#uXM{6EWoA9oOe(SkRpgj!u~JfWYktFQI;9Aa#Rso; z6r#5mqj{k-lTfpC<&HBt3$Wq72l~CE*;FL4K5{ZRkHsAQeK;k0XY6sDko_9vC;bX8 zDmSs%U@WUtiT)~$+wFp7jOZtiUM&`PUZ%c)vqj3~D^<_=D3$%VUpXY~ z@htT9TQqXjfF4rwzP#Hiycw1&-zD>fRGW9}Dh{!?H1FRv?ix(_uSTv45U*;qWv-D% zik9&V-FcjKj8Av%{26}ayh6v_)j(?Ink>aQt1AHUum;mC#@yb zA}O2(FRHyMuhqJ8&GC}3YpV?%I?ALh*eC^fok4gOD?>MSUNV}zs6xU;y4R;) z^eJLP7~f1@ zfQW{y`XDs>)rmZ^tiXK#0P?nckaks{R{e9+^~-EB^*x;BJ_P7H0u(EPYRUxn8_g^U zvvZX5rY5%yQ_~eiGMekwGWzQ>wXdZbD{C?|?y(-Cn69H4fo7*u=msYwQoV6m+Mc~| z)6l%;Q2+^Pk&!-`PI!-1%Gp(B%|Yk^rI0mk>6-I6TuDi4ymfe6$EvS9em8t5)%(-( zKy`AwdK6gIUCS#5AS#ZlD)HS!Q6xOy zY^o~4l-gAFjcAyl-oBHPh83pNsvc$er3&J=WMnj?)S#MH?Xjm+QK>wAQ{A;fXXGe5 zSe&yc#c$`P{%cAGaj~v&+?=~Igi>(NfLU>zCMXWAtBtJUl#g6lp3AJ<{-bC7Y3Vtt zVjhaSFhy_4&zbMfwZAA5f3>pppXN3u@%*A($MQ1s{oodtYhq18y7;wkOrt&^?V8&Z zMm`OKKpnerh|a|sU3xHkJ9Mo70H0u@oZ#b?dRG-8_lG>{>x6xBBbcTcL}MbZaJduOlZoh{^VQXhkVN^xKeGG={{Smua%6MJ3IgH={(Q=@R!ou()J4bF zRacA9zQ04{8JT>+PQ|{3R5k@1xh#?AwDhi8nKBywD0%@gUa7>U|nKQEnF(`aZ!6kpSlbC>*P_DD7CfPq1j1 zmMqOSqmzsGYrjQA?Kuu75*XDT)w$@icYZvFA&;3E=h*sn$!)Ub5S9BFnU-BtEr#T^ z_{i(ci*P69dIi=1aX^m0nkSsY5*I8xHQTaU1W@8HHC9973*gQboys3DKCc9vYPC zoq=9>ds;yH^E9#Zhntny^VyIMetLsatMW@(6y`Jjn`p$hl-)nrmZ!~pUudjN8)WvpFmN#x2(x3shNFWP(VMY(S{J(U>gESSmdj zK6ApJa)+)>iB&+siCmKst{rlu^yt{PG+-0v+j{qD7-o&iOkNDsuK14yDB@OX70T;hudX%GIB`lM4N%aoI@g} zVuhqj@Zc!mZ7Y!Q{*_@g?yh*_8j3P6+Mene_StEvr?Ip@6{k5rqDkQ=&|^=#Md7Hplj04GRr+Z10lZus>ihWNdab8BgsYFU*^6@7O`%Y8C?F4Oc? zUg2_fJ>#+RTn27ktPZ&^+)86D@RMG}i%Cf=tE?%KoF@&9*lW$UJFKkC)1nO8*y40_ z8GARV`<|UlzU%tzwe$4NY5C;G8QkSPUXs@yLs_%WgV9iM6A%N5ETNwc0<-o}BFmLP z?D14td>&XYiQ~5} zj6f8)$JreF1;(ieXx^TMm<7uA$n5o31o+8!SvntFxH*6#>NzjeA1kmCPEAq|;Hq&*J zb}Y-qJ5aPvd?BXOHA(B7bSB|5LurVf*)E%O16ydE`&C^Sy0}VxTow0q0R94P_HKaP(2pUCw0;tM$Z0ckgRA=fp zeQ8mfW?No(%TEmPM@#gns_y+?ILWvs_%>!0Tten9P0CKO@G zr&Pu~<1ZM0&pZLZJ-EOGhh=y4B5&rb0T}Yk|0Txzr@O% z{{R6wo*@iTo0+jWPVbYKB8V3Ve#+#;r41?FS+!Vahb9l(D#|ln3iP^^$m>%m8BWMt z)?OB8typxcYQmX06snxG+~AN!A64}VS-#X#v->miP?!Y|pIqI5zbfWgfgQ~q>tDefS6lT`*q@oU46SQ^Nb6-u)!|5b*Z%3TqwoW(g zO=c}e>yxPzho`L%o-(sBP^~55YWUt~9s+5pVanB1Ui@Nh5nGU1+MQ{xcPF>1$%x~Q z0K|)ygiB>mt844>)K^@$3>8_7z7*f12=>6VP$)w7X3sc;>SkB$dY5Q88D9(mR;)W0 zQ;fKdqaxXFmXOM@VqKFaRj`>)4JYR1E14fDfXhVl$syS5%3QbyysL?V6n@zgvpd#$bAGL!HFc7(_ z%_=tK&OME?e5=jXGJHKMR3Yuh1*au(Meprpa$_OLP`Ji@dwHO4LE{}d0D;7$sg0~I zzmU*fZ2XSX(8N(N>@#7z3>yGsx|E4au>6YXB4~|FS#yw9Oj-ra<5t9pS#Fl{)=8v$d|y?&C)8WEH*&l@$W;;X z?Ovo83)R7l|nJgM|W%UzORP)&G8b#VgA6k*9 zreEZ1K;?$SjZbmF2uEDmcFlBl2pD8X4Dtq(i>7m2w=a^oN*2b~>nJLm^59uZWFSLZ zRI^Z-q`+apTwbKtkSIQ4++aO`R#~HW&!NVET3D#W4@@;BQ3nM`7OM(FgB}9q_&BIn z1zL;#`SUQHxv)l5l7sr_xo+z@3acx9o~Jy>8*3erwWU5RjVxYU42}cFGWJ+Hs?V}# z^95*I3lghV89QdHaP(3$*c|Q)Aw!$bDYMWCFso!mr%hE_4tZz*xzmT(6ezdvn-mL* ztJSr+Pa+Iv7SxX~{V9`!d9Y`|oDLRv@Rb8ikoD&#tPn2@0-R zrkb(o15fzPP%p3hQQFXHrAG)j2t#O>WYlQit1qeAC8vzqZDlTT#}Srg;ZxM>a(H^wJfli zh*|eu0cj7K7F5@ZHd9;-Ls+gY(0}XJlDTgqV|<&2A_F>!(u0$HNQ1wZB4bg{G9ts@&5qL-rN95 zWQjOb%PnSh1GZQ>tT}wES0(hvf1=b3eU7x-+4OF5i`ybRu^*gT4&1PLnkfu{I+AVd z1WC*B$5ZDwrC71yd(Rd762Qc89QF%?Zk;If zd_0UN;JE8Bayp+_K$Y?ZFI3z~avLMps-P{{pVcBXS>X4LH=j!Ayyv8>F_{{S=X z+0Y!Dc(*;OY*#x2jZ$-1&w^16+Y8Y`qwO4Y_p+{l3b-ErjGaTpS<% zwi%eL&PQD32mnL4sOt0W#Lr6Vk=ZHs4aREFD7yB~BBw=r-*vdlH!b!!M-*jjGUGfQ zWi$_riWkgH+T64l&;(x0I5Xizc@NMsb?cLx0^y4w%|$u4_;s8q%4V<#9m2@#7s0PY z%SVOP*6oyDGf%3ue%a+uPO1~-YH87$pC9dFR~Rp1;c-t^)32)7_cxivRXDR!8VA#2 ze2s9xD|XFCQJXj81DdbwEQ{Ma(4_wWn(S@0U1{4Kgc^>$wtBS@&mf7?pXJhPkEpJ+ z1mjDl080=Cb^9pcs>ZVU?uVh1^MOa7ZbDp)hYpn2b#H166q8eCXP+fm&y!BfnXui% zH%zniSnL~yR;>YPh+1T)%FnkV#I@KItIW0h#!BLgI(=z1n$DD5U?`GSmQ~9wqA3-C zic{;CR?0IKPTWC%y9oqonsn2N+Q6i-W_mUMQ` zugG9i)6h}RMjhALdUP#~z!3YpY7TB+9X`7ni(KB*DqaehqPXlDhn}doj4_=|hcOB} zVvdG%`JTfn%VG8h>ajcUsh8sAe->H0pdYogM}HCe^Dot;>i(QZ_DGM|#KF~kRD_Ww zgQ{#tTgzMp1)8i744aQXC(jw;__H5Du}<`Qe6scf@6^>!5Vc020*W}0LM5u)J$e;o zFJU8vJE7G=%OzH}v0w^_%|gE8uUQohO8)>zpfuPA7gCC<*qm%_EW%TT>AFag#Z0$n zMo-kQ6h;{W)W$=U;Iuf`#Ode1HDMXDFV*wRoYxB?_B_&|A6oF{4_1MYEa2Lp)prW)`a><@>&O{m2i+p0KINxHSR9LokQbDvWQhsbE_w&bCkw|>uV57w zPB0T`vCA=4+umhOuGggd3=PIB9@H(KMb4hRTrp9cz zO3hWJH3a_v`8s!YAJR%QWhTZ&5vxvFM^#`OJUV8}9WC+TyQpJWPGKZ8y%WOzj zXF+B9ig*h_!)y>XHn_$--598XHQQ|mGWuq&%Dk1B3o>&$oMZDk5Pka!ZFOyG&9T-e zD1N=j$}(}$aiiWahZvdf#x*FcgNzHqJqd5$j-gPqWcfL;4_2p9G#SQGOoQw( zW?uQKfv~4+5)9r%KG*%8t%yAtNnBf$5+t2{kTQE6m&=^t;2!15ne>-JDL&L*7e3FH zqrBxZs245JmS3_|h^Ws=h3Dk?7O4xLV_OtZj(hobW&v>z+O%F~zNM$xeOTf>Jnga; zn&=Fj5stigZ!ug}hOvA4Vum@p3v8~YiJG^NZHt16Njw3KVp~&T<(h`1wJPm7GPebS znvnYnsZGg+m+U&~FPEN5<;IE-5vv2?`ZBwj8Ec|De zY_fa=!!X%$L6>I5;Z}eeYp5*<&Y2xRa+;N#$NTfrLu@`!2RiZ-YC4>$D!Tsw?yjWK zzQuF>=BQ-KT)OeX!h9fLo_N3QN(GVG`|N?lIK(|MSL8YzEsb8ms#`n@B(>PK&a){! zNZDBoRT#ZVp$ZPuB(>g@3&#wsh_C5Hw}X-FWnZGX8Tppoa$69IUN>R@l4^p0=YFOsWe99QAz3?Gvg5J zAe=V3WCu9FwrinQ+;F)TBRDUU;ZGnPg`LWv;&$uD@w{TtdD_;qPMno>c*TSU*cpC%_MtJ z97T0kQWw|>j&g)hKZr`FWtj0-y10!;8m~6X>~WiQc5QTHg&5?KI?=(+P<-NzOop-m zE7v`piFf2}Gcc+N-GfGR8x2Y-FTXCW>L=7S4`bP}eqEe}_aR^zY54n()SYN(_I`IZ zn?B{Xrpuadlb71Z`a6_5`y6B)Z5LC+Fc=8OXAG3X&HHK+&Kauh~m)nBZ7(v!(- zNGjNOt$99KHKMCpsLi_mfb~@mX^s~kvt!JG*RE3B=Ww%U#^hnGTQ=6G03{t1FXN^= zSZ9%QvoIWD14phaM!tr;@9d=@lZ zTAZNnN~u>N0(T`{)n&8>3n|EL_0Ml?DPxv^Bm7Nd%8SW8h{bO=nHj)yK<$k;YA9Kj zs*zF-f9c8RVwF{NFfn zl<3;tXixKFvgp~!c3yng@asX$deb&kAwsUOm|EMPTMB1itkF(1P~|7_ROBEEyDmcd z@Y-wJAfz-Ht6OdS<;g6zqUv@T1szHZqj8PVf`Fxa@YCs*W6C$yEz5DqX`GCU;~p3G z6E8xQ_4mz+4#`D)Sg;Be=8Qq7AnUVmtKGa7Y)30P$rhCDlpHSJyVn%}&k!+}zB~_4 z#nhRi8l>n3GWB%(WvEnY>?iTS~t~Ok*}=2beDO4f=?^17@|DE zX8=x3Iu0JAkWidYm1P90rcrz3rd3_~QdAg8&iv;c+hSlenyS<6+4|$3)9;#n=KlbU zNK}v~kF8ca`XQ5NT*oLx&+b2IRFDZwqpeR0xilG5){I9nqh)5a!iIS=8$bR3069e& z&siY^usN^E#Z%sH7Nl~%Oq91Sp^R}mC#Wyb;6;Eyg3 zJQ((-JX(3zj1H}gt({*vPShg8(5ImK<8l@Y5p;IIr{xE`}##WS5?jjA0ge0*?!B6uT=ZZTr_Bo|mp^-Gp0l=E3J$hoNeCR{$vYR(^IXwcgB5(@1c&jy!n|&#aGGMlI z!H?Lx5V3FR)0LtGNTSh-j>=2pBO^&!sO3~DBFVq)Bo$eX%Nb50Vy36dChtZ-syp%> ziN)g*WS1zp{{UlM6e}|J2ZN=z!huUDP{N^Bjn}@wIWo0ShK&*B5ZOoORA&s%0X(t) z01e!%+9WfC?IOTkNGcSsJ#h)6{kxzZd~}&&SI9E7ml+jK&-e?={x_3Ph_u?&427ow z_Eh>Atk{}1Ydff78kL{aN!7b&b7r~f(bfu+QcRcY&zPRiMyK9fF-DsAkpg~YgmoA> z+Igyy*xj6mt^w6%P&L?$S_g@U#Q{>}GKq%DX{`(B{Kn9gcJCxH4*RNGL8jT9jk8%ALBqC*;-I8*Fml z#URo!==4eJS3g~|VnHUT?7lNpE6T{CVzQCN4G0s&V?6EM?x{SM$@4X$Q)7Gv*1dKE zaxC3WN6$7T!w{V&L$y1M1>CxI&&cV%!s%2A&E8a_H8akBJaL;mE^<*e;o3n&)BPR^ z*v3dQA-e`8otWaM8LRNx*OKMm_8OhV9(}S3dd+3qax2+pqI)-(7uc;5Uy-sW{DVCs zP|>O2nlj?u`!5*WOhNe1HDUtf6V<4O4#*4DQ;9@kK~-tNZF-Qp>^(h9v-Ub>ujDC_tfU(khQ*UMM^$oK zUpmuCVu4kTxhd3VT$^@%p64XWl!g5>Yx*K=x~OL1DduhRSN@{N!EC%<NsN8>sSC3{ZG zCTCW{iVo!gP7x#zwn|68+l5q2PnFuM2jxWd%9X3PW@hc^YSaG!6WKcJZMWF0_Sj<} zb@OJ;enwFX2AQ0Kla`7i_=3QN&1)Qc621lVs-sPl7A@bJ#_ArFAS$EA=rC zLul}u8V$vD?iCR7-FX`S0AU2-U`9N?kxoH_njJyguTc6&zRH=m944-~V5%_Gt15~S z6p4G|{{Td2m185=D`DW{D-q_|KH;^==0D~rTPrh0vJ|Y?2C}evp*Ra-g4x<^v-9c4 z_1p?;-^(Y~i`(Iqn;@n@t5G7IG8N!j&6=#oElk&$?4SwBj&$^3uFX~+sNQT(T* zj=8Mj(`f`!q-R61v9Yh>TeB#W3RZ<1XJDD7yEdlIU3n^~p^=M80%er4>m@}f#jrJ0 zsBwfiZvb+w$bW~_Jxf#>>$hB<$1f&Q!mOb4ar*3{c3^14F{2#xcWN{XEa*2JbM z;nu`r*{Icu3|6AU(R$H=GjORO8y1FivWpj)Tv}H-BqFEGv1WBuNWf1h&FS2nWk7*LonPYnXPlo}51!vRBr0q=;>ZM$4BkkX z>($$ts3pXrrw?hax#+E6xhk55JyHx`A?f7u?%Qz-meyNl{*z9Rtm=5-Q<-5r;bq06 zK2Lxv`5_E{$kLQevI=aozw8dNp(D6PhRnkndh6=Ne_LTvNwEI_!g8+E$vo0Z#*tDN zR)%SGg{_e#Jt3 zV3B6zN#mY!JB)T6Uye~oX6@EYPI~laPU|nKPU2a! zS#9IZg2Zw!7MpS;8T7_+Y$RWz?20^gX&HYU+^nb>A8%#?-aYlaN z?`?%S`z?unGJoQSjA71AJ3DhR*|S_J&7bnT@5^M$bH_#xZwU&zYLM=^1)rqO*1SIh!b)(<#|=#Yv{T!mnjM zT;)N0+GJHV^jjj&COIL(b;}dzHx^-I67^2)I6Jt<5 zd8|Sws}kvo5VbX!9>3AY0=7PC!;Z_(0ItX`%Ob0&PDZ@pVZ?tZy5oQH&qi&M>e4+{ zT?%ZeWkmzo7eDQNVZfha&)gn*53>rV^DFS9jEBZj;oHl&Eb+npaf_}=h(G%?s8*p` z$>{I2yoQikEXPsk>`>nWI#Ap43Au*K*G~6wXaDqmw1;iVq!`8IKLH z>dYuQRCAqXGnjzHWl0FKI2g-1H7VH!QBV~ESyu(VaSI%7)tr%$X2qSzX8V@h0ICK# zZr;v&=8EEv1V1A`QlH&*s3(y0i6dU{wZ&d z_~AM0N=lspdcg9ixoMKK1cjMVMOMZiXs2BA`|*p*75K&4E0Vw0Udm8#a-Dq>?M;gI z&4&e1mkWq0IBO@{8ig>=ld`<#xdM9wj84N7u*POMpwRySwp-B#x6V|KP_INiqKoxf zs;Mp5f-0qXbN2m)$)CE-P7VfZnG~(iC8Q~5*I|{5DSxSG3KWCIt2cb2olNmA1Cd=l=j(KT{KM5x4^(}JBRZx)ie#U@> z)plGhUPE?d3&K%lo%;nmrFqFG4A4-Dz~^GYAE*>(JOwI849*Jx(~$bAvbQB!z8Ya) zHrR2hIG>?8=J?&y8G4FNTrY-iax-6Hok5dA9YV3}D8Q=Cv#TzDs_N{SwdyL=LUMC5 z$B^^7fRjoxLt1_d%xQE5W)){eN0yGMn^R1@q73a7XbI4^ZMS@B@Jwe#+0y!M!?V&7r1l;!fBWv{QUD>^+9=)~n2-&>dDx$9oERDPJR%|6Q1C89|W-{{x) zk7m!=^T9zwLOi+;J$2~Sny^*sB*zaG8=r~Qs^9VcHETdW?aY}JeAq@@j}4s51lC#D za<(Ciz|Nov^eeDJ9WXiL0z`gN!oZ4jLAyL6*>c=M*7~O+TLzwHbt4@l| zs&FC8Csm*N&#Pn9OpTDs$)bV9B+9L@RJ^2O%SNNqUz#XAP zegh|)-UyXxGVDLiAE2QOPx|r7$Ne-5Hce9|{4!PshzpWm#>W#5a+ggyA+X>e8;~B;;B+>X(`#Ucy6+E>9XYBRH*#?Zu z+3nK>7@E_zDuix3sbDkl@+UYzsuUYPCFw$v?@R@;rQarw*w~UP$o)kxp0n)7lS1i= zPY+~f{eI4=HCj+K{Ftzzl@V3VLeCWgq`?N2`uYzf!>=n9Lu!_&k0rnm}caCumV_j?ets&k?fGk@T;|URM&nJg)AJk zb_0g>pLczIBaso{YR@LYOtu0t~%IOjoZ9KG(R6&O#>IFGC8;qGRO9+Xv zA;9K=ed@EEb6|I=lJZ3vwV+oI9eh*Thy@CkW#DHCib9YVD!opr9op~h`wXh8Y8Z6Q zv?C(`b7p)s7?BwepcPsZ*I7HqWq2+26|n0*?3}2`%kSW(pRPFBKV*`&KUJklichgs zhh!}|;;&}eiCm1O!mK;dkW+^lG$9sB(n+4|>&mES>wX!KW2D5=?X8vCEQ?ac{{SJ+ z+g*vKnKo5VipVVexkl>G0Ahj^3qG%a*{KPfJQfseG zqV-`Kuw8eXC7YV8>5S7jS09fcK7Kg=04mAZW}ITX4A-gSTXEIDZ6xvhl9WxcTzjWj z{!yi$^HMFV`7IV$ZTgmPTy1qZs})>>tGDJxv}sMbXF}7wzESFiJ1+H(*XzA59?eB% zWs~BS>}n)k`-!$VZ#kjyRegr263x~7w;{PR7gyqM>l)w755*FO&qeyJ37xw$0O2D1 z9d4{HIb@|3&CyV7q0Y?H*W3PlL1)6yO%5`ZU&!eDX7B$18r-&DO1h^(__&oW$jxZUlNqQ_QIt&mlZ(`0Ol?L*tc51(1rH+% zjIt1TAR-(y7_0TC2(sXY9{}-ziK6_s%IEU|<{K5=GvI(ZS}XCcRcKsxDjE84>B+}o zlMB{^m0`lKB=MaH#itBNIMY_iDke8#QOmhzD?T_``WBmF>-H)+&3iD-nsv|EbDI@q zVMe68V>srldvaSN$aX;3@7F)ZRgVyB^0I9GWp<;S{pB$wKx>312I-=O!H3p$0n0KJXvWsAPKvN)>+7G zj?`7`t;SFK0D*CstdfjYPEJe?T{~vN5rLRvTkWYp!De#Gi#X7g`w_=QZbn!Eos$_< zAcJ}txX1JcU7I~M!n+m+iDdXF-|VP*KRi`iv`1mtT>LI~;gyCe_d5)-2aI;-G&y3j z0egj#*SV|mWURDDcYA!diix*$Y9I;b-AgA`bI+3SszcL)y#4g`CQihTnNjLGcgkse z_$VCRVfFb7H&@owHUyJ8v^Glv$+QEXWx! ztOxs1hHR-p&jl2uRe4^$nd8kKS?$$dvBvpsjo*cyYV97eyKH9P4?iBZ?K7}dLwd{z z@|aiaMeCl(xb6Y&8x=bqsn#r$&$Hy0jP%7$*zBMMVi8;u78q3Z1mNw~M}^ySMsD3T zyAuhoS=a?e9p~Jn=h0Y&YqMJ#EtBLEPo&3O`}QH&l|6yuJorYGU0!@-`<0!0lgBS$ zDeTNdof*$K0s->Eo#tnDIn=T0S0ea+N|Hl=C)e5l)0$-vBR0|j_Mv5U9WmrYS&je$ z9b&-`o>-2{{<|9=NLFJCuVr1S8gJg9g8qEv_i%@#xRD_{3cOLpC!dnr1o34PAD8W&r(0ZGB&luTQ5P zaYJWi84v+)^0p0&vdfd)?T=lMY~QXzZ9@iG6=QhRi z4YnKHp%}9CY7?C~MD5vGhCvS{Sh((>9{A7jOBqI}vt|2{?!#R=)l6Edv`L1Mpf|~& zS{}+$z+)bD$@;T14y%gI2W57`8=eYIHkX<-`l_#;J!IOudd{g&t(qQtJG$t@@{u|J z0LWT(Fi?!H?V8&3+s2QZ_|Ri9D682XeF*tbY0kRm961485HTi7mJ3?coc)Fv)KXSN zuD-JQ(oC5}W}H@yZOs$u)`7aIeU^4AfQgVW_T;}f(`-`7o!H>#l~dYkqdD)DKvrtg zS8mxF1W@6XsQ4ktS*Sv)2M#byoHHr~y5XSC6_fS29VS)o0)`zOv#T&d!GzF+UbgC` z-F}*tD9&gz{0aE;ZhJ$u1r$v##IkqAcMgc*DCxrqw?OZ>GRiy zSMH6HUfJRfDETx|Lw;7aBEPfB>`;uoJ1V~!{>D?qmTMq_ObyPlZM+$h*gk(<{)Ex6(e*6(yQDy?qS)V4RN1p3TvNY%$Jrq$HdV}_3*`2JE zE87tL{wbgT07g}u?Xh8+<<|m^RF@Y=DMV;yxOxLVr%V8}9Acu7HNu4IFt-?L$j|pz z)&VcBdg_Bbof499>wuun!=9kM9aBEzGtPry1O~bzeJ8T5KF( z`k1oi*o@?|%puKo2-1G|5b~pJWq9ffj3ws;cn(o@wYh1Dm0nzu3vsp-)} zxC}alPEF9ZJi-F2)uj?HT%E6?z=ch4%Bk4lZz9}g+(=zW8RStq>q=m4H~vE}zzk{h zIe(KVRsLa3PSmSC8p`9tZ9vs{;!ZXruYyJS_JSf5KF z89IWlf~Ipt&KYx~P(^uLpE=E_tH-`H(hcz8(bqZ$WrvhIaf7Kw;TQO_G}ZI$wC;r} z0Zn2&0xRNZ>-Oqq%v*(UsWzJ;r+j7eq1Yk6V0fjOoxjX#w`|oyl%;`10gr+%Dxl4dNtXh1f2?;UfPz5>%Sf1g1|UelxTlA<{W%2Zy(xft{6dLA^Nl)nk;Oen z!95hYumkqMr8WYl&cHe79h;0U?>~dG^={u01`G z!FF(~^$OEG>FzSmXr{vH*UvSTw#VyvqQPA^e;!V4Nt8sQuyq*JRK+JEvlzqEH73Dp z!sOjD4!L^~lGrE?$!w<8NHr2l^47l@Rr4Lre~`gLQLW#H2}eC;MJa7wZJe5-`} zG>;2q#dT~w$U?&pVTi$V^~Xr7fd2qE4}7k~zT8cu0HK4vmg0V~6RdOa)2^$Ny{bArXxj4nyBp8hzxzCH!=L0gYnaON*YE;qO)MPm5zw2(~5QKCAnObZQ z^Rp3})F(GcT;w)W{OcmB$(yxk?Sz0h1w~B4x-z_;g%Ocos$im|&sq}$*}+8g?9wKf3(A$SVu+Yx31r`}{PYV0Z~ zzie-naC5j^)iN)3E@8mnSDv{8Chda3M`XB!xu(x$1FsQ~%2j~jsg_Zc>4w1#UxkFI*vF_7IW(;Ea!9VC{>CdSc zi`}Y*V^9`#95Jw&U5{LtVisL-U`~IWZ>uk7Z8u4$bVs{Am1pLS-@DVyPKK+YL4l06 zKVeAw2W%C{1Y`cG!I|bD>Eeu$%cPE4Z^$U9ESP8RWpLm ztfPkv#*s)j#V`(y!mfNabWk@OmF&-&z%FVrQmyf?EM*I7>-@@OEi9dNigs;q=9<$? z@UUhVRI`w&(6C-dBsDg-GH_=}&zv~xTzM79utHiCV!*IzPIFYEqmT^P(#&UzRO