From 274e2a45318138833c759128b43c1a8abee252a3 Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Thu, 16 May 2024 22:05:17 +0300 Subject: [PATCH 01/28] Update README.md fixes #119 --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d9f27e27..cf307967 100644 --- a/README.md +++ b/README.md @@ -175,17 +175,19 @@ pipeline1C() Если у вас есть расширения которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы. * При загрузке из исходников расширения должны быть в том же формате(edt или конфигуратора) что и основная конфигурация. -* Для загрузки расширений необходимо описать каждое из них в массиве (`initInfobase` -> `extensions`) +* Для загрузки расширений необходимо описать каждое из них в массиве (`initInfobase` -> `extensions`). + Для загрузки расширений в информационную базу необходимо выполнить следующие шаги: 1. Укажите имя расширения(`extensions` -> `name`). -1. Определите метод загрузки для каждого расширения(`extensions` -> `initMethod`). Поддерживаются два метода загрузки: +2. Определите метод загрузки для каждого расширения(`extensions` -> `initMethod`). Поддерживаются два метода загрузки: - `fromSource` - загрузка из исходников; - `fromFile` - загрузка cfe-файла. -1. Укажите путь до расширения или URL для скачивания cfe-файла(`extensions` -> `path`). +3. Укажите путь до расширения или URL для скачивания cfe-файла(`extensions` -> `path`). - В случае загрузки из исходников - необходимо указать путь к исходникам расширения - В случае загрузки cfe - Укажите путь по которому будет скачан cfe. На данный момент можно указывать как локальный путь, так и url для скачивания cfe(Прим.: https://github.com/bia-technologies/yaxunit/releases/download/23.05/YAXUNIT-23.05.cfe) +4. Укажите этапы сборки, на которых должно быть загружено расширение (`initInfobase` -> `extensions` -> `stages`). Если оставить это поле пустым, то расширение будет загружено на этапе `initInfobase` и будет активно на всех последующих этапах. В противном случае расширение будет использоваться только на перечисленных этапах. Пример конфигурации для загрузки расширений: ```json @@ -194,7 +196,8 @@ pipeline1C() { "name": "ИмяРасширения1", "initMethod": "fromSource", - "path": "путь/до/исходников/расширения" + "path": "путь/до/исходников/расширения", + "stages": ['bdd', 'yaxunit'] }, { "name": "ИмяРасширения2", From 3087a046191df83e9018f9645b84a86688fd5b5a Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Fri, 17 May 2024 11:53:44 +0300 Subject: [PATCH 02/28] Update README.md --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index cf307967..a56016ff 100644 --- a/README.md +++ b/README.md @@ -174,20 +174,20 @@ pipeline1C() ## Настройка загрузки расширений Если у вас есть расширения которые необходимо загрузить в базу для проведения тестов и проверок, это можно сделать на этапе подготовки базы. + * При загрузке из исходников расширения должны быть в том же формате(edt или конфигуратора) что и основная конфигурация. * Для загрузки расширений необходимо описать каждое из них в массиве (`initInfobase` -> `extensions`). - Для загрузки расширений в информационную базу необходимо выполнить следующие шаги: 1. Укажите имя расширения(`extensions` -> `name`). -2. Определите метод загрузки для каждого расширения(`extensions` -> `initMethod`). Поддерживаются два метода загрузки: - - `fromSource` - загрузка из исходников; - - `fromFile` - загрузка cfe-файла. -3. Укажите путь до расширения или URL для скачивания cfe-файла(`extensions` -> `path`). - - В случае загрузки из исходников - необходимо указать путь к исходникам расширения - - В случае загрузки cfe - Укажите путь по которому будет скачан cfe. На данный момент можно указывать как локальный путь, так и url для скачивания cfe(Прим.: https://github.com/bia-technologies/yaxunit/releases/download/23.05/YAXUNIT-23.05.cfe) -4. Укажите этапы сборки, на которых должно быть загружено расширение (`initInfobase` -> `extensions` -> `stages`). Если оставить это поле пустым, то расширение будет загружено на этапе `initInfobase` и будет активно на всех последующих этапах. В противном случае расширение будет использоваться только на перечисленных этапах. +1. Определите метод загрузки для каждого расширения(`extensions` -> `initMethod`). Поддерживаются два метода загрузки: + * `fromSource` - загрузка из исходников; + * `fromFile` - загрузка cfe-файла. +1. Укажите путь до расширения или URL для скачивания cfe-файла(`extensions` -> `path`). + * В случае загрузки из исходников - необходимо указать путь к исходникам расширения + * В случае загрузки cfe - Укажите путь по которому будет скачан cfe. На данный момент можно указывать как локальный путь, так и url для скачивания cfe(Прим.: https://github.com/bia-technologies/yaxunit/releases/download/23.05/YAXUNIT-23.05.cfe) +1. Укажите этапы сборки, на которых должно быть загружено расширение (`initInfobase` -> `extensions` -> `stages`). Если оставить это поле пустым, то расширение будет загружено на этапе `initInfobase` и будет активно на всех последующих этапах. В противном случае расширение будет использоваться только на перечисленных этапах. Пример конфигурации для загрузки расширений: ```json From 1c21631b0fa46e60d228a20a6421bc6b16e0a742 Mon Sep 17 00:00:00 2001 From: Dima Ovcharenko Date: Fri, 17 May 2024 16:20:05 +0300 Subject: [PATCH 03/28] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a56016ff..81345d32 100644 --- a/README.md +++ b/README.md @@ -182,14 +182,15 @@ pipeline1C() 1. Укажите имя расширения(`extensions` -> `name`). 1. Определите метод загрузки для каждого расширения(`extensions` -> `initMethod`). Поддерживаются два метода загрузки: - * `fromSource` - загрузка из исходников; - * `fromFile` - загрузка cfe-файла. +* `fromSource` - загрузка из исходников; +* `fromFile` - загрузка cfe-файла. 1. Укажите путь до расширения или URL для скачивания cfe-файла(`extensions` -> `path`). - * В случае загрузки из исходников - необходимо указать путь к исходникам расширения - * В случае загрузки cfe - Укажите путь по которому будет скачан cfe. На данный момент можно указывать как локальный путь, так и url для скачивания cfe(Прим.: https://github.com/bia-technologies/yaxunit/releases/download/23.05/YAXUNIT-23.05.cfe) +* В случае загрузки из исходников - необходимо указать путь к исходникам расширения +* В случае загрузки cfe - Укажите путь по которому будет скачан cfe. На данный момент можно указывать как локальный путь, так и url для скачивания cfe(Прим.: https://github.com/bia-technologies/yaxunit/releases/download/23.05/YAXUNIT-23.05.cfe) 1. Укажите этапы сборки, на которых должно быть загружено расширение (`initInfobase` -> `extensions` -> `stages`). Если оставить это поле пустым, то расширение будет загружено на этапе `initInfobase` и будет активно на всех последующих этапах. В противном случае расширение будет использоваться только на перечисленных этапах. Пример конфигурации для загрузки расширений: + ```json "initInfobase": { "extensions": [ From 60c93cdb1f39233cff84159874bed4620b987aa4 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Tue, 6 Aug 2024 08:30:55 +0200 Subject: [PATCH 04/28] Fix plugin download --- settings.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index 2a475b84..ab2b122a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,7 @@ pluginManagement { repositories { gradlePluginPortal() + maven(url = "https://repo.jenkins-ci.org/releases") } } From 13d0dbf3adcfc81a498cc51ae2181cd0dda7ba0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 06:33:57 +0000 Subject: [PATCH 05/28] Bump gradle/actions from 3 to 4 Bumps [gradle/actions](https://github.com/gradle/actions) from 3 to 4. - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/v3...v4) --- updated-dependencies: - dependency-name: gradle/actions dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 1c1e5550..d27ea4bb 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -21,6 +21,6 @@ jobs: java-version: '11' distribution: 'temurin' - name: Setup Gradle - uses: gradle/actions/setup-gradle@v3 + uses: gradle/actions/setup-gradle@v4 - name: Execute Gradle build run: ./gradlew check From a5613f424b327539e60859c4e5afbf141eb92dbd Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Tue, 6 Aug 2024 08:46:09 +0200 Subject: [PATCH 06/28] Create rebase.yaml --- .github/workflows/rebase.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/rebase.yaml diff --git a/.github/workflows/rebase.yaml b/.github/workflows/rebase.yaml new file mode 100644 index 00000000..c06a1bcd --- /dev/null +++ b/.github/workflows/rebase.yaml @@ -0,0 +1,19 @@ +name: Automatic Rebase +on: + issue_comment: + types: [created] +jobs: + rebase: + name: Rebase + if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase') + runs-on: ubuntu-latest + steps: + - name: Checkout the latest code + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 # otherwise, you will fail to push refs to dest repo + - name: Automatic Rebase + uses: cirrus-actions/rebase@1.8 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 60e184c14c0e1c56d9bd8c4d0caeedbc0462656d Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Sat, 24 Aug 2024 13:24:25 +0300 Subject: [PATCH 07/28] =?UTF-8?q?=D0=98=D0=BC=D0=BF=D0=BB=D0=B5=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8F=20=D0=B7=D0=B0=D0=B3?= =?UTF-8?q?=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D0=B8=D0=B7=20dt=20=D0=B8?= =?UTF-8?q?=D0=BB=D0=B8=201cd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + resources/globalConfiguration.json | 2 + resources/schema.json | 8 +++ .../configuration/InitInfoBaseOptions.groovy | 14 ++++ .../library/steps/CreateInfobase.groovy | 68 +++++++++++++++++++ .../library/steps/GetExtensions.groovy | 36 +--------- .../library/steps/InitFromFiles.groovy | 16 ++++- .../library/steps/InitFromStorage.groovy | 16 ++++- .../jenkins/library/utils/FileUtils.groovy | 32 +++++++++ 9 files changed, 156 insertions(+), 37 deletions(-) create mode 100644 src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy diff --git a/build.gradle.kts b/build.gradle.kts index afd047aa..dd06aaf9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,6 +11,7 @@ plugins { repositories { mavenCentral() + maven(url = "https://repo.jenkins-ci.org/releases/") } tasks { diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 693f5544..4d0496c4 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -42,6 +42,8 @@ "initMethod": "fromStorage", "runMigration": true, "additionalInitializationSteps": [], + "baseDBPath": "", + "vrunnerSettings": "", "extensions": [] }, "bdd": { diff --git a/resources/schema.json b/resources/schema.json index 326c1e0a..3c63f642 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -173,6 +173,14 @@ "type" : "string" } }, + "vrunnerSettings" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию не заполнено, требуется, если на этапе подготовки база загружается из архива.\n " + }, + "baseDBPath" : { + "type" : "string", + "description" : "Путь к конфигурационному файлу эталонной базы данных.\n * По умолчанию не заполнен.\n * Указывается путь к файлу *.dt или *.1CD\n " + }, "extensions" : { "type" : "array", "description" : "Массив расширений для загрузки в конфигурацию.", diff --git a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy index f1b7e1aa..593c2832 100644 --- a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy @@ -25,6 +25,18 @@ class InitInfoBaseOptions implements Serializable { """) String[] additionalInitializationSteps + @JsonPropertyDescription("""Путь к конфигурационному файлу vanessa-runner. + По умолчанию не заполнено, требуется, если на этапе подготовки база загружается из архива. + """) + String vrunnerSettings + + @JsonPropertyDescription(""" + Путь к конфигурационному файлу эталонной базы данных. + * По умолчанию не заполнен; + * Указывается путь к файлу *.dt или *.1CD. + """) + String baseDBPath + @JsonPropertyDescription("Массив расширений для загрузки в конфигурацию.") Extension[] extensions @@ -62,6 +74,8 @@ class InitInfoBaseOptions implements Serializable { return "InitInfoBaseOptions{" + "initMethod=" + initMethod + ", runMigration=" + runMigration + + ", vrunnerSettings=" + vrunnerSettings + + ", baseDBPath=" + baseDBPath + ", additionalInitializationSteps=" + additionalInitializationSteps + ", extensions=" + extensions + '}' diff --git a/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy b/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy new file mode 100644 index 00000000..57febbb3 --- /dev/null +++ b/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy @@ -0,0 +1,68 @@ +package ru.pulsar.jenkins.library.steps + +import ru.pulsar.jenkins.library.IStepExecutor +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.utils.Logger +import ru.pulsar.jenkins.library.utils.VRunner +import hudson.FilePath +import ru.pulsar.jenkins.library.utils.FileUtils + +class CreateInfobase implements Serializable { + + private final JobConfiguration config; + + CreateInfobase(JobConfiguration config) { + this.config = config + } + + def run() { + IStepExecutor steps = ContextRegistry.getContext().getStepExecutor() + + Logger.printLocation() + + def env = steps.env() + + steps.installLocalDependencies(); + + String baseDBPath = config.initInfoBaseOptions.baseDBPath + if (baseDBPath == '') { + // Не указан путь к базе данных, создадим пустую базу данных. + createBase('', steps) + } else if (baseDBPath.endsWith('.1CD')) { + // Это файл базы данных 1С, просто скопируем его. + String pathToInfobase = "$env.WORKSPACE/build/ib/1Cv8.1CD" + FileUtils.loadFile(baseDBPath, env, pathToInfobase) + } else if (baseDBPath.endsWith('.dt')) { + // Это файл дампа БД, скопируем его и создадим БД. + String pathToDt = "$env.WORKSPACE/build/tmp/dump.dt" + FileUtils.loadFile(baseDBPath, env, pathToDt) + createBase('build/tmp/dump.dt', steps) + } else { + Logger.println("Неизвестный формат базы данных. Поддерживаются только .1CD и .dt") + } + + } + + private void createBase(String dtPath = '', def steps) { + Logger.println("Создание информационной базы") + String vrunnerPath = VRunner.getVRunnerPath(); + def initCommand = "$vrunnerPath init-dev --ibconnection \"/F./build/ib\"" + VRunner.exec(initCommand) + + if (dtPath) { + // Загрузка из dt в vrunner 2.2.2 не работает корректно, потому инициировать через init-dev не получится. + def loadDtCommand = "$vrunnerPath restore --ibconnection \"/F./build/ib\" $dtPath" + VRunner.exec(loadDtCommand) + + def updateDbCommand = "$vrunnerPath updatedb --ibconnection \"/F./build/ib\"" + def options = config.initInfoBaseOptions + + String vrunnerSettings = options.vrunnerSettings + if (vrunnerSettings && steps.fileExists(vrunnerSettings)) { + updateDbCommand += " --settings $vrunnerSettings" + } + VRunner.exec(updateDbCommand) + } + } +} diff --git a/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy index 68bd9502..4fac658e 100644 --- a/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/GetExtensions.groovy @@ -54,7 +54,8 @@ class GetExtensions implements Serializable { buildExtension(it, srcDir, vrunnerPath, steps) } else if (it.initMethod == InitExtensionMethod.FILE){ Logger.println("Загрузка расширения ${it.name} из ${it.path}") - loadExtension(it, env) + String pathToExtension = "$pathToExtensionDir/${it.name}.cfe" + FileUtils.loadFile(it.path, env, pathToExtension) } else { Logger.println("Неизвестный метод инициализации расширения ${it.name}") } @@ -73,22 +74,6 @@ class GetExtensions implements Serializable { } } - private void loadExtension(Extension extension, def env) { - String pathToExtension = "$env.WORKSPACE/${EXTENSIONS_OUT_DIR}/${extension.name}.cfe" - FilePath localPathToExtension = FileUtils.getFilePath(pathToExtension) - - if (isValidUrl(extension.path)) { - // If the path is a URL, download the file - localPathToExtension.copyFrom(new URL(extension.path)) - } else { - // If the path is a local file, copy the file - String localPath = getAbsolutePath(extension.path, env) - FilePath localFilePath = FileUtils.getFilePath(localPath) - localPathToExtension.copyFrom(localFilePath) - } - } - - private String initVRunnerPath() { return VRunner.getVRunnerPath() } @@ -108,21 +93,4 @@ class GetExtensions implements Serializable { steps.unzip(sourceDirName, EdtToDesignerFormatTransformation.EXTENSION_ZIP) } } - - private static boolean isValidUrl(String url) { - try { - new URL(url) - return true - } catch (MalformedURLException e) { - return false - } - } - - private static String getAbsolutePath(String path, def env) { - if (path.startsWith("/") || path.startsWith("\\") || path.matches("^[A-Za-z]:.*")) { - return path - } else { - return "${env.WORKSPACE}/${path}" - } - } } diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy index e08fa32a..48fa280f 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy @@ -6,6 +6,7 @@ import ru.pulsar.jenkins.library.configuration.SourceFormat import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.VRunner +import ru.pulsar.jenkins.library.steps.CreateInfobase class InitFromFiles implements Serializable { @@ -41,9 +42,20 @@ class InitFromFiles implements Serializable { srcDir = config.srcDir; } + def createInfobase = new CreateInfobase(config) + createInfobase.run() + Logger.println("Выполнение загрузки конфигурации из файлов") String vrunnerPath = VRunner.getVRunnerPath(); - def initCommand = "$vrunnerPath init-dev --src $srcDir --ibconnection \"/F./build/ib\"" - VRunner.exec(initCommand) + def command = "$vrunnerPath update-dev --src $srcDir --ibconnection \"/F./build/ib\"" + + def options = config.initInfoBaseOptions + + String vrunnerSettings = options.vrunnerSettings + if (vrunnerSettings && steps.fileExists(vrunnerSettings)) { + command += " --settings $vrunnerSettings" + } + + VRunner.exec(command) } } diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy index 888dde1f..ff34cba2 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy @@ -10,6 +10,7 @@ import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.RepoUtils import ru.pulsar.jenkins.library.utils.VRunner import ru.pulsar.jenkins.library.utils.VersionParser +import ru.pulsar.jenkins.library.steps.CreateInfobase import static ru.pulsar.jenkins.library.configuration.Secrets.UNKNOWN_ID @@ -43,6 +44,9 @@ class InitFromStorage implements Serializable { String storageCredentials = secrets.storage == UNKNOWN_ID ? repoSlug + "_STORAGE_USER" : secrets.storage String storagePath = secrets.storagePath == UNKNOWN_ID ? repoSlug + "_STORAGE_PATH" : secrets.storagePath + def createInfobase = new CreateInfobase(config) + createInfobase.run() + steps.withCredentials([ steps.usernamePassword( storageCredentials, @@ -54,8 +58,18 @@ class InitFromStorage implements Serializable { 'RUNNER_STORAGE_NAME' ) ]) { + Logger.println("Выполнение загрузки конфигурации из хранилища") String vrunnerPath = VRunner.getVRunnerPath() - VRunner.exec "$vrunnerPath init-dev --storage $storageVersionParameter --ibconnection \"/F./build/ib\"" + def command = "$vrunnerPath update-dev --storage $storageVersionParameter --ibconnection \"/F./build/ib\"" + + def options = config.initInfoBaseOptions + + String vrunnerSettings = options.vrunnerSettings + if (vrunnerSettings && steps.fileExists(vrunnerSettings)) { + command += " --settings $vrunnerSettings" + } + + VRunner.exec(command) } } diff --git a/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy b/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy index e7a0f6c2..8ad5f0d5 100644 --- a/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy @@ -41,4 +41,36 @@ class FileUtils { .replaceAll('\\\\', '/') .toString() } + + static void loadFile(String filePathFrom, def env, String filePathTo) { + + FilePath localPathToFile = getFilePath(filePathTo) + + if (isValidUrl(filePathFrom)) { + // If the path is a URL, download the file + localPathToFile.copyFrom(new URL(filePathFrom)) + } else { + // If the path is a local file, copy the file + String localPath = getAbsolutePath(filePathFrom, env) + FilePath localFilePath = getFilePath(localPath) + localPathToFile.copyFrom(localFilePath) + } + } + + private static boolean isValidUrl(String url) { + try { + new URL(url) + return true + } catch (MalformedURLException e) { + return false + } + } + + private static String getAbsolutePath(String path, def env) { + if (path.startsWith("/") || path.startsWith("\\") || path.matches("^[A-Za-z]:.*")) { + return path + } else { + return "${env.WORKSPACE}/${path}" + } + } } From 3f12889ceba7357b22e34ed931a35ff74023c2de Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Sat, 24 Aug 2024 13:45:16 +0300 Subject: [PATCH 08/28] =?UTF-8?q?=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BB=20Re?= =?UTF-8?q?adme,=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20vrunner=20?= =?UTF-8?q?settings=20=D0=B2=D0=BE=20=D0=B2=D1=81=D0=B5=20=D0=BC=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 ++++++++++++++++++ .../library/steps/CreateInfobase.groovy | 2 +- .../jenkins/library/steps/InitFromFiles.groovy | 2 +- .../library/steps/InitFromStorage.groovy | 2 +- .../jenkins/library/steps/InitInfoBase.groovy | 7 +++++++ 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 81345d32..afa8d63c 100644 --- a/README.md +++ b/README.md @@ -208,7 +208,25 @@ pipeline1C() ] } ``` +## Загрузка эталонной базы +Реализована возможность загрузки эталонной базы на этапе инициализации информационной базы. Для этого необходимо указать в конфигурационном файле параметр `initInfobase` -> `baseDBPath`: + +```json +"initInfobase": { + "baseDBPath": "путь/до/файла/базы.dt" +} +``` +* Поддерживается загрузка файлов формата `.dt` и `.1CD`. +* Путь к файлу базы может быть как локальным, так и удаленным (URL). +* Если эталонная база содержит пользователей, то необходимо указать файл конфигурации, который будет использован для дальнейшей инициализации базы данных. Для этого необходимо указать параметр `initInfobase` -> `vrunnerSettings`: + +```json +"initInfobase": { + "baseDBPath": "путь/до/файла/базы.dt", + "vrunnerSettings": "tools/vrunner.json" +} +``` ## Настройка шага YAXUnit * Добавить расширение `YAXUnit` и дополнительные расширения с тестами можно в `jobConfiguration.json` -> `initInfobase` -> `extensions`. Они будут загружены при инициализации ИБ. diff --git a/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy b/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy index 57febbb3..e7350c54 100644 --- a/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy @@ -59,7 +59,7 @@ class CreateInfobase implements Serializable { def options = config.initInfoBaseOptions String vrunnerSettings = options.vrunnerSettings - if (vrunnerSettings && steps.fileExists(vrunnerSettings)) { + if (vrunnerSettings != '' && steps.fileExists(vrunnerSettings)) { updateDbCommand += " --settings $vrunnerSettings" } VRunner.exec(updateDbCommand) diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy index 48fa280f..70fb0a98 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy @@ -52,7 +52,7 @@ class InitFromFiles implements Serializable { def options = config.initInfoBaseOptions String vrunnerSettings = options.vrunnerSettings - if (vrunnerSettings && steps.fileExists(vrunnerSettings)) { + if (vrunnerSettings != '' && steps.fileExists(vrunnerSettings)) { command += " --settings $vrunnerSettings" } diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy index ff34cba2..a9f24de4 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy @@ -65,7 +65,7 @@ class InitFromStorage implements Serializable { def options = config.initInfoBaseOptions String vrunnerSettings = options.vrunnerSettings - if (vrunnerSettings && steps.fileExists(vrunnerSettings)) { + if (vrunnerSettings != '' && steps.fileExists(vrunnerSettings)) { command += " --settings $vrunnerSettings" } diff --git a/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy b/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy index 981e52e4..c1e36d07 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy @@ -43,6 +43,13 @@ class InitInfoBase implements Serializable { command += executeParameter; command += ' --ibconnection "/F./build/ib"' + def options = config.initInfoBaseOptions + + String vrunnerSettings = options.vrunnerSettings + if (vrunnerSettings != '' && steps.fileExists(vrunnerSettings)) { + command += " --settings $vrunnerSettings" + } + // Запуск миграции steps.catchError { VRunner.exec(command) From 4108f9858f182bc9eb49916ff83eacba79245f75 Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Sat, 24 Aug 2024 14:13:42 +0300 Subject: [PATCH 09/28] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=B8=D0=BC=D1=8F=20=D1=81=D1=82=D0=B5=D0=B9=D0=B4?= =?UTF-8?q?=D0=B6=D0=B0=20=D0=B2=20pipeline1C.groovy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vars/pipeline1C.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index 731e9eeb..e8a20f9e 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -113,7 +113,7 @@ void call() { } steps { timeout(time: config.timeoutOptions.loadExtensions, unit: TimeUnit.MINUTES) { - loadExtensions config + loadExtensions config, 'initInfoBase' } } } From 632fc87eb80bfadc48bc3587baf264af9ddeda56 Mon Sep 17 00:00:00 2001 From: Ivanov Egor <80944823+Segate-ekb@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:27:18 +0300 Subject: [PATCH 10/28] =?UTF-8?q?fix=20=D1=83=20initInfobase=20=D0=BE?= =?UTF-8?q?=D0=BF=D1=86=D0=B8=D0=B8=20=D0=BD=D0=B5=20=D0=B2=20lowercase?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy index ced8c88b..425b6682 100644 --- a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy @@ -83,7 +83,7 @@ class LoadExtensions implements Serializable { return "" } - String optionsName = "${stageName.toLowerCase()}Options" + String optionsName = "${stageName}Options" def optionsInstance = config."$optionsName" From eefbb8944911ba17e6fd255f2a3c175b99c314b6 Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Sat, 24 Aug 2024 22:32:56 +0300 Subject: [PATCH 11/28] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=81=D1=82=D0=B5=D0=BF=20createInfobase.groovy,=20?= =?UTF-8?q?=D1=83=D0=B1=D1=80=D0=B0=D0=BB=20=D0=B4=D1=83=D0=B1=D0=BB=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D1=83=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B8=20=D0=B7=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=81=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D0=B5=D0=B9,=20=D0=B2?= =?UTF-8?q?=D1=8B=D0=BD=D0=B5=D1=81=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B1=D0=B0=D0=B7=D1=8B=20=D0=B8=D0=B7=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D0=BB=D0=B5=D0=B4=D1=83=D1=8E=D1=89=D0=B8=D1=85=20?= =?UTF-8?q?=D1=81=D1=82=D0=B5=D0=BF=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 - .../pulsar/jenkins/library/steps/InitFromFiles.groovy | 4 ---- .../jenkins/library/steps/InitFromStorage.groovy | 4 ---- vars/createInfobase.groovy | 10 ++++++++++ vars/pipeline1C.groovy | 1 + 5 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 vars/createInfobase.groovy diff --git a/build.gradle.kts b/build.gradle.kts index dd06aaf9..afd047aa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,7 +11,6 @@ plugins { repositories { mavenCentral() - maven(url = "https://repo.jenkins-ci.org/releases/") } tasks { diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy index 70fb0a98..2bc967bd 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy @@ -26,7 +26,6 @@ class InitFromFiles implements Serializable { return } - steps.installLocalDependencies(); Logger.println("Распаковка файлов") @@ -42,9 +41,6 @@ class InitFromFiles implements Serializable { srcDir = config.srcDir; } - def createInfobase = new CreateInfobase(config) - createInfobase.run() - Logger.println("Выполнение загрузки конфигурации из файлов") String vrunnerPath = VRunner.getVRunnerPath(); def command = "$vrunnerPath update-dev --src $srcDir --ibconnection \"/F./build/ib\"" diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy index a9f24de4..cf1c2130 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy @@ -32,7 +32,6 @@ class InitFromStorage implements Serializable { return } - steps.installLocalDependencies() String storageVersion = VersionParser.storage() String storageVersionParameter = storageVersion == "" ? "" : "--storage-ver $storageVersion" @@ -44,9 +43,6 @@ class InitFromStorage implements Serializable { String storageCredentials = secrets.storage == UNKNOWN_ID ? repoSlug + "_STORAGE_USER" : secrets.storage String storagePath = secrets.storagePath == UNKNOWN_ID ? repoSlug + "_STORAGE_PATH" : secrets.storagePath - def createInfobase = new CreateInfobase(config) - createInfobase.run() - steps.withCredentials([ steps.usernamePassword( storageCredentials, diff --git a/vars/createInfobase.groovy b/vars/createInfobase.groovy new file mode 100644 index 00000000..e908d851 --- /dev/null +++ b/vars/createInfobase.groovy @@ -0,0 +1,10 @@ +import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.ioc.ContextRegistry +import ru.pulsar.jenkins.library.steps.CreateInfobase + +def call(JobConfiguration config) { + ContextRegistry.registerDefaultContext(this) + + def createInfobase = new CreateInfobase(config) + createInfobase.run() +} \ No newline at end of file diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index e8a20f9e..93f87e14 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -94,6 +94,7 @@ void call() { createDir('build/out/') script { + createInfobase config if (config.infoBaseFromFiles()) { // Создание базы загрузкой из файлов initFromFiles config From b503ae67eee6ddfc33ce8996a3b2b284e67c46a2 Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Sat, 24 Aug 2024 23:06:33 +0300 Subject: [PATCH 12/28] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BB=20=D0=BB?= =?UTF-8?q?=D0=B8=D1=88=D0=BD=D0=B5=D0=B5=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9F=D0=BE=D1=81=D0=BB?= =?UTF-8?q?=D0=B5=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BE=D0=BD=D0=BE=20=D0=BD=D0=B5=20=D0=BD=D1=83=D0=B6=D0=BD?= =?UTF-8?q?=D0=BE.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jenkins/library/steps/CreateInfobase.groovy | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy b/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy index e7350c54..702aab37 100644 --- a/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy @@ -28,7 +28,7 @@ class CreateInfobase implements Serializable { String baseDBPath = config.initInfoBaseOptions.baseDBPath if (baseDBPath == '') { // Не указан путь к базе данных, создадим пустую базу данных. - createBase('', steps) + createBase() } else if (baseDBPath.endsWith('.1CD')) { // Это файл базы данных 1С, просто скопируем его. String pathToInfobase = "$env.WORKSPACE/build/ib/1Cv8.1CD" @@ -37,14 +37,14 @@ class CreateInfobase implements Serializable { // Это файл дампа БД, скопируем его и создадим БД. String pathToDt = "$env.WORKSPACE/build/tmp/dump.dt" FileUtils.loadFile(baseDBPath, env, pathToDt) - createBase('build/tmp/dump.dt', steps) + createBase('build/tmp/dump.dt') } else { Logger.println("Неизвестный формат базы данных. Поддерживаются только .1CD и .dt") } } - private void createBase(String dtPath = '', def steps) { + private void createBase(String dtPath = '') { Logger.println("Создание информационной базы") String vrunnerPath = VRunner.getVRunnerPath(); def initCommand = "$vrunnerPath init-dev --ibconnection \"/F./build/ib\"" @@ -54,15 +54,6 @@ class CreateInfobase implements Serializable { // Загрузка из dt в vrunner 2.2.2 не работает корректно, потому инициировать через init-dev не получится. def loadDtCommand = "$vrunnerPath restore --ibconnection \"/F./build/ib\" $dtPath" VRunner.exec(loadDtCommand) - - def updateDbCommand = "$vrunnerPath updatedb --ibconnection \"/F./build/ib\"" - def options = config.initInfoBaseOptions - - String vrunnerSettings = options.vrunnerSettings - if (vrunnerSettings != '' && steps.fileExists(vrunnerSettings)) { - updateDbCommand += " --settings $vrunnerSettings" - } - VRunner.exec(updateDbCommand) } } } From d43d6bdc8254b07e2aa34d048134f674b033770d Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Mon, 26 Aug 2024 11:27:17 +0300 Subject: [PATCH 13/28] =?UTF-8?q?=D0=92=D1=8B=D0=B4=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=81=D1=82=D0=B5=D0=B9=D0=B4=D0=B6=20=D1=81=D0=BE?= =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B1=D0=B0=D0=B7=D1=8B?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/globalConfiguration.json | 1 + resources/schema.json | 4 ++++ .../jenkins/library/configuration/TimeoutOptions.groovy | 5 +++++ vars/pipeline1C.groovy | 8 +++++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 4d0496c4..48547371 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -28,6 +28,7 @@ "bdd": 120, "getBinaries": 60, "createInfoBase": 60, + "loadSources": 60, "designerToEdtFormatTransformation": 60, "edtToDesignerFormatTransformation": 60, "edtValidate": 240, diff --git a/resources/schema.json b/resources/schema.json index 3c63f642..7c025a6f 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -106,6 +106,10 @@ "type" : "integer", "description" : "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " }, + "loadSources" : { + "type" : "integer", + "description" : "Таймаут шага загрузки исходников в базу, в минутах.\n По умолчанию содержит значение 60.\n " + }, "initInfoBase" : { "type" : "integer", "description" : "Таймаут шага инициализации информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " diff --git a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy index 900f6a90..89eb92a0 100644 --- a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy @@ -21,6 +21,11 @@ class TimeoutOptions implements Serializable { ''') Integer createInfoBase + @JsonPropertyDescription('''Таймаут шага загрузки исходников в базу, в минутах. + По умолчанию содержит значение 60. + ''') + Integer loadSources + @JsonPropertyDescription('''Таймаут шага инициализации информационной базы, в минутах. По умолчанию содержит значение 60. ''') diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index 93f87e14..2750b2cc 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -92,9 +92,15 @@ void call() { steps { timeout(time: config.timeoutOptions.createInfoBase, unit: TimeUnit.MINUTES) { createDir('build/out/') + createInfobase config + } + } + } + stage('Загрузка исходников') { + steps { + timeout(time: config.timeoutOptions.loadSources, unit: TimeUnit.MINUTES) { script { - createInfobase config if (config.infoBaseFromFiles()) { // Создание базы загрузкой из файлов initFromFiles config From 5abf4198cfc5bd4af95fd34fd5a9c28885138555 Mon Sep 17 00:00:00 2001 From: Ivanov Egor <80944823+Segate-ekb@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:26:11 +0300 Subject: [PATCH 14/28] Update vars/pipeline1C.groovy Co-authored-by: Nikita Fedkin --- vars/pipeline1C.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index 2750b2cc..c3dab0e7 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -97,7 +97,7 @@ void call() { } } - stage('Загрузка исходников') { + stage('Загрузка конфигурации') { steps { timeout(time: config.timeoutOptions.loadSources, unit: TimeUnit.MINUTES) { script { From 6b900452f9f323da862a91f1a0ca507f2d6c31de Mon Sep 17 00:00:00 2001 From: Ivanov Egor <80944823+Segate-ekb@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:26:21 +0300 Subject: [PATCH 15/28] Update src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy Co-authored-by: Nikita Fedkin --- .../pulsar/jenkins/library/configuration/TimeoutOptions.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy index 89eb92a0..aad73b01 100644 --- a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy @@ -21,7 +21,7 @@ class TimeoutOptions implements Serializable { ''') Integer createInfoBase - @JsonPropertyDescription('''Таймаут шага загрузки исходников в базу, в минутах. + @JsonPropertyDescription('''Таймаут шага загрузки конфигурации в базу, в минутах. По умолчанию содержит значение 60. ''') Integer loadSources From 55ff0d26a88e2ac2ad0d76842bef074a4177e525 Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Mon, 26 Aug 2024 12:47:20 +0300 Subject: [PATCH 16/28] =?UTF-8?q?=D0=97=D0=B0=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB=20baseDBpath=20=D0=BD=D0=B0=20templateDBPath=20=D0=A3?= =?UTF-8?q?=D0=B4=D0=B0=D0=BB=D0=B8=D0=BB=20=D0=BD=D0=B5=D0=B8=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D1=83=D0=B5=D0=BC=D1=8B=D0=B5=20=D0=B8?= =?UTF-8?q?=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +++--- gradle/wrapper/gradle-wrapper.properties | 2 +- resources/globalConfiguration.json | 2 +- resources/schema.json | 2 +- .../configuration/InitInfoBaseOptions.groovy | 4 ++-- .../jenkins/library/steps/CreateInfobase.groovy | 13 ++++++------- .../jenkins/library/steps/InitFromFiles.groovy | 1 - .../jenkins/library/steps/InitFromStorage.groovy | 1 - 8 files changed, 14 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index afa8d63c..52a23d08 100644 --- a/README.md +++ b/README.md @@ -210,11 +210,11 @@ pipeline1C() ``` ## Загрузка эталонной базы -Реализована возможность загрузки эталонной базы на этапе инициализации информационной базы. Для этого необходимо указать в конфигурационном файле параметр `initInfobase` -> `baseDBPath`: +Реализована возможность загрузки эталонной базы на этапе инициализации информационной базы. Для этого необходимо указать в конфигурационном файле параметр `initInfobase` -> `templateDBPath`: ```json "initInfobase": { - "baseDBPath": "путь/до/файла/базы.dt" + "templateDBPath": "путь/до/файла/базы.dt" } ``` * Поддерживается загрузка файлов формата `.dt` и `.1CD`. @@ -223,7 +223,7 @@ pipeline1C() ```json "initInfobase": { - "baseDBPath": "путь/до/файла/базы.dt", + "templateDBPath": "путь/до/файла/базы.dt", "vrunnerSettings": "tools/vrunner.json" } ``` diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4b44297..ffed3a25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 48547371..b363d66d 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -43,7 +43,7 @@ "initMethod": "fromStorage", "runMigration": true, "additionalInitializationSteps": [], - "baseDBPath": "", + "templateDBPath": "", "vrunnerSettings": "", "extensions": [] }, diff --git a/resources/schema.json b/resources/schema.json index 7c025a6f..987d88bf 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -181,7 +181,7 @@ "type" : "string", "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию не заполнено, требуется, если на этапе подготовки база загружается из архива.\n " }, - "baseDBPath" : { + "templateDBPath": { "type" : "string", "description" : "Путь к конфигурационному файлу эталонной базы данных.\n * По умолчанию не заполнен.\n * Указывается путь к файлу *.dt или *.1CD\n " }, diff --git a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy index 593c2832..6570c079 100644 --- a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy @@ -35,7 +35,7 @@ class InitInfoBaseOptions implements Serializable { * По умолчанию не заполнен; * Указывается путь к файлу *.dt или *.1CD. """) - String baseDBPath + String templateDBPath @JsonPropertyDescription("Массив расширений для загрузки в конфигурацию.") Extension[] extensions @@ -75,7 +75,7 @@ class InitInfoBaseOptions implements Serializable { "initMethod=" + initMethod + ", runMigration=" + runMigration + ", vrunnerSettings=" + vrunnerSettings + - ", baseDBPath=" + baseDBPath + + ", templateDBPath=" + templateDBPath + ", additionalInitializationSteps=" + additionalInitializationSteps + ", extensions=" + extensions + '}' diff --git a/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy b/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy index 702aab37..c7ee28f2 100644 --- a/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy +++ b/src/ru/pulsar/jenkins/library/steps/CreateInfobase.groovy @@ -5,7 +5,6 @@ import ru.pulsar.jenkins.library.configuration.JobConfiguration import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.VRunner -import hudson.FilePath import ru.pulsar.jenkins.library.utils.FileUtils class CreateInfobase implements Serializable { @@ -25,18 +24,18 @@ class CreateInfobase implements Serializable { steps.installLocalDependencies(); - String baseDBPath = config.initInfoBaseOptions.baseDBPath - if (baseDBPath == '') { + String templateDBPath = config.initInfoBaseOptions.templateDBPath + if (templateDBPath == '') { // Не указан путь к базе данных, создадим пустую базу данных. createBase() - } else if (baseDBPath.endsWith('.1CD')) { + } else if (templateDBPath.endsWith('.1CD')) { // Это файл базы данных 1С, просто скопируем его. String pathToInfobase = "$env.WORKSPACE/build/ib/1Cv8.1CD" - FileUtils.loadFile(baseDBPath, env, pathToInfobase) - } else if (baseDBPath.endsWith('.dt')) { + FileUtils.loadFile(templateDBPath, env, pathToInfobase) + } else if (templateDBPath.endsWith('.dt')) { // Это файл дампа БД, скопируем его и создадим БД. String pathToDt = "$env.WORKSPACE/build/tmp/dump.dt" - FileUtils.loadFile(baseDBPath, env, pathToDt) + FileUtils.loadFile(templateDBPath, env, pathToDt) createBase('build/tmp/dump.dt') } else { Logger.println("Неизвестный формат базы данных. Поддерживаются только .1CD и .dt") diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy index 2bc967bd..8e9ba36f 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy @@ -6,7 +6,6 @@ import ru.pulsar.jenkins.library.configuration.SourceFormat import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.VRunner -import ru.pulsar.jenkins.library.steps.CreateInfobase class InitFromFiles implements Serializable { diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy index cf1c2130..fbd04c10 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy @@ -10,7 +10,6 @@ import ru.pulsar.jenkins.library.utils.Logger import ru.pulsar.jenkins.library.utils.RepoUtils import ru.pulsar.jenkins.library.utils.VRunner import ru.pulsar.jenkins.library.utils.VersionParser -import ru.pulsar.jenkins.library.steps.CreateInfobase import static ru.pulsar.jenkins.library.configuration.Secrets.UNKNOWN_ID From 9f07d3e23a59da5bb780a0c1258fc597cfa09bf6 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Mon, 26 Aug 2024 22:08:18 +0200 Subject: [PATCH 17/28] gradlew 7.6.1 --- gradle/wrapper/gradle-wrapper.jar | Bin 55190 -> 61574 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 292 ++++++++++++++--------- gradlew.bat | 56 +++-- 4 files changed, 216 insertions(+), 135 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738cbd051603d91cc39de6cb000dd98fe6b02..943f0cbfa754578e88a3dae77fce6e3dea56edbf 100644 GIT binary patch delta 41382 zcmaI7Q*@@!6E&KNZQHh;iEZ1qoj1SIL-&x=KuAW}q)pxsV z?`Kz4T0L0!K3D_Y57_Y2HBTy75D){b<~Scm6BjDT(xP=nHg6|Y#L_SZWdhBfFjhF${-d!WSV1ZwAtt20f&&!4Mp(naVpziD48t^fm@n8~+VuL$SKi*j zgY4I|V8`lTdwihLUGJN`q`8tv5_}(V9xvAy{F}Z7edV5gKZ#v(19TiCFDCZW02THl zNke?#f7-JrQfjHLM1A<}p+jZH`FKCJd`NQ%cm$ucQ>qc4-JVYhrr-)F#4z|wCo+0u z3+T7qr25w!5S4Z0$8GE)X##30Q0GI|0gT(jAN-6mk-EA}eo(sf5EYqLRxycr6j{M4G z@HKS~DPJj0n-Jx*C?Oa7*(kSk{R^etM6F!~Qb^VSwOYo6{cPI7>sR7VMS#%~H=W}p0O+kK0KWilaFBBU@JzLdr& zk7|__R3ku?+VVx>N{_?!L=u#0U?xDY;fnKnmMtXwf)irb9Q9OGbmZDXZ18s+jacjnX`)bJ%7uWi^=Tma<59VM9NkaR$kpqaomScXCFhsLBo2p7S*`F; zZMirFM2|GA*>CTLjHv4H0Q_Yq^fg=VXg1uqL-<@~T^yTN!GNFNSOCu-lvjGZ2%^Hv zI#~9mS@2wO4I1o!k%d%lf#F1lRKq+JN&&P4Y<58m-;%kuuQUN=`zNnq!G<=k7y&c% zSqifb0vvs|X+_5YO&isl4L>zx%0IRoHe^d2`)Qw`Q^egrp zalhgKQcz#2MwOa(^V>j&_?A)?iC`KtY0B@UDKyYn!g1eq8dXlNMek|B zwNAjH^bZE1N~?U?4(rYhnYM4`U(}%)<&mrsI*UE{^nhSR?Lrj`HoW7O82&Y@x47gTc0#T(L`p?U?aUt4C2M)0H6vN$;52K` zva8cve-YQ(i^Y&}RLp55r!99bbJDY2)$yx_f;<)F$!1cxrcF!^#PO`ZQQfK+;w3+8 zxoU$g5}wD`r4}m(pNu3hsmB=lGE+2q_HfXnskqXL3DD3l8`J$%a>cnp2)b{A`8aUC zVJT#9B#h5U80|m?1e)c|p0O&+GPPp;rdo~oPR9$={J0lMt(|Om!F$fI&b_oWWnOA? z9W!TWiLlJ@DaBESJxe6)Cg$JDJ>0}Op7tWR=Vh=uivt;P;-7NDzmqXnM7f^7<$u5h zi_3vj1gJ(c-OLcuN1s@6HS;nuRX@cjoL$wemzPdlr(`-biUYm1GPjzM%Vg?qcM8VE z=8x62n`0J$j7;nrQLkHrt}ty>bE6%Ji*y`IO6A{OWlL7s#UYWK#+{BuE2@*_*eY}u z`SvuU8!Q|Od8k9~@qPmxSX_c%GC+m=q}`-)0Iw+*Wx3RKU3M2t7Z^oTu~Wa;x|;nG z4!d~9y+JqmuJ$Kc8V@B?Tb!raYf%VU_(KAVLg^DXK?^g{Zf+xARvjhima>TDUYoDi z_b;ee%_B^oc^Ua_nk=(F6H~#ec50<|>rNKRh0>~+f5?*E3(#ds?b$vE-C5Oxqb!Z3 z0dwVs+;HW8ipodb#uS)dYaYnCc-CeRk`)PQ^FGN!HD9i1z2YV09?X1FH0y3xC5-56p^I{K$GB#`>@5 zMwlI7!VloDyv<38ix4mO1A z$XY^(?`~uS*C4AWKgtNyuM+fvc=aMzesN2L>v6{UIQ1&AZdq_KOG2;Mn1ejf`9td0%3ltl!1v zn!j-8^2Yal{-9i1g=d`DTZC`Z_on(INx8uLQ|Jw8G}vLhKFGqEvz&j zrLidw%B4HaZS^t{t@4oL|Pg_XP@;E(vdHn3K1 z^nq5P=44tSS*WBgSlSGU#JvGhV~6;U`W;6=B~3fdCiY+}pTX-=6dmZN;NGD}MjKN6 z%62*yCloZTaE4W)_W1|5j|tzLo;`%R#JD(Wr2+D$#DyY^c#Hs=z3j2N_mZRr?N*1Y9PX ze}R@R#%6Zr44y8=PEO`73{J)_#`flJ|5gtFzOIZ;E{^}U-K@=B!T#N7-mwfvK{$Q2 z?vn)r0qKJQ0pUw_&L>YcpT|wE^M(U7Fep_K|3;w`VM+;x)>8U$tV0c*wAWXve<89# zu_f*Ykw2)}FBT$W^0)jhGsbz=A!t>l4IA}4XKFgfv6qLB%{Sod>mK7LQ5rcrsfMCx zeJJHH`S8MtxX`sTywf&T76}ag5Iz#O1i9CpQgEmwemu`8w#|&Djo|v!eBv@7){fqG zJTnJX_GEcIw6~SQHnXIPCb}t6GX`8cz9P#;&@AKJh4XuB5Y;m35_P8ojWaE%kzS@n!*VXcgMv}R~NL-9No1;GON-4fgEldEz6wx`5oZVkW) zTd+?*i>v%&qNZLnC<6{qo7EmMJEgzIu6#nEuqVu8z;vcp*`(=&{t|xpWB^ zCNzivEBU-1py-RGV`YcV%NdQ!3B@E^lxkL6LguSCh|#a3yh{SW8FIh3DDExB3XS-) zFb@S396)=E!Nuw=^dNaB2m-rpWwt&Su_Jo&g-TdO+|!4Xw7Q5Uq{V%vZwi+98Q3V! z-b~TbU^-aapkK77tutB39cF1$^WqmZ;3^eK{1yvoGf1#6~Sg2BBV zl}8|HNLR2fmq@1-a1>RX-JjVCt9=)(p0OSI5vzkO0F-;+?yxVh)WDN=nD<*E+pi0} zU0aCch9vo|=}b;csOwzBXkg(S zVNH))6g6E09J6CLwXgZ>3i=)L(X7wGXO^MIw+?A5qJeXF)!!X*?cC?9y6Do=!19&a4eX?EHXc^wshHRi* zBDC(rTN+p1e2u?w6zP2r6ge{cShY^obp5)m$O+PM(h!}-?$*x=kXmYKIF!~92+ZI@ z8V~Fzqx|QT{TFusuvOAdlZMpb)|o9Jh>od;cWAw%HIj6D77eW+T(*~(OrHbOM%<@a zJZfI%b5&WL|-UI#vwo(gmnL?I#u zswJd|?1f;$Qv87pm3F93(KqnoN5j0E{SQ|XC232kMJd7P2NEBWnhmAp1I?0Y{i;HZ zb;!l(*b#+^Z1^~NX)G3WGj{yTZZR&1 z3^zqy_Sl{y_oP3n(oZ**2lz7(5aZ=%Nb|$oF}wf8D->NH`R6}&aEAi{;s1ZxfoTB` zFrsmxvZaCi7019GM~`|4iMqMSy9|B{0VdtQ9tsZKfeuyfE@HcwO^>cQkjB=ueT4B2 z?H}z{Mv%nX^VhcgW?s^|+?O2ca-Dc-Lhc`5{>ac!zLE*6q|}JKYT#)TK~oSJ+#dN_E25xx$hHr8p;>$xyy@r#Krmu$|b^AO094_xsA;5%hSQNIv!t<_RDf{@i>q> ztryXV_D!t;7ck#{`2l$-cdoY$h2PL-?XC z>AvtTg{uwhlQ@Y9Lj=4_!M+eDEJa4xC*0R;l^erJt!8~BDaO3J8&9N`di37m1zR=|&-2H6pluRe?j1CS0z&Ah6# z--xFbAsxwm9zJHj&wT6-fHLrS0_r6OM5#44SqAlzOKguo#;4o7ay>(Yt%{Ng>|cZP zlm%59tM=j1wahzm-tO%Hb+=ze%EZ_=5Cfc0cQ|&YFIx^Z-9d{>It{+Z?2o*tv?nQ9 z>Zw-Rm%$JFcX9+N*M*FpVSPf~(zf4lUg;m-(VfH6HKZavOUSKy^ysJ~*%|?_Vhm72 zTPL&Hf()NAY~p~XThKxQ_^-}*Cl(&ko<*OF4zz^8cft;EUD6CqmdP}h(K?cWI1;d9nHZbQr8jg5gX)&}B%y++}K z47@s;xW7Nb6imvzsvgF_d>t01(0Y7PodXOQNZge`v<)MdcqJi}@nH^%Qn7 z^)oNZp`e7%&YOy?&TEebviho1q!s`ABN*1ejh~|>A_@uL_=Uh4?K!jyZ0CtVvsY=$ zmHGnSLWq9>n{Q;6Md-L~Xs3{XC{y0NnY?Xg%wlGmP zPF*&cZ|qkT8$@4goojXiRPdz(HG=VulGDY;q7$K_`9rtDMxJ#+l&F(`>hB`5AvT_} z2JI2V{t*--Y!{BwlvX^Mp?;&G49$1!oa_NPW3-RyfHtSYzQ9AD=Bw~|V>tYoKd&Eb z(x&$ou9g~LDW&*DN{ZJy6@;%9FP*2tZUVKwf{0Gq@3xA5Z5(oqwhn*y(ugq%1w@&3 zOxU3~Zwl|i&C`8_`7gY5i+!<{AVEMVQIee#sge;E@c}bhXP#*4=-)k@GbKwuWD{w{ zoyAU*+=7DnG;GByTEuHH=@{WB5)ez++$|P^KYE!eeyt)Xfh(&i>DB;qiwU{-zcBI+ zclY)yUS{PMDS}%3?x%bmue(0plMKJ#?(sloUezQR9MY8|_{g_uim~xzVT$gWBGb8< zU<}+Ob^!DwIKuhhqNAjCiOS)%elp_ohLC8OWC-IGqxyfXWu45`Oqhd7a9He;8worg zW&~Ir`g>x$48dR6j)GXXe?fVBOAQYBeL@=w>4cBn28NDhKEl8#%6Q5AY=qPsV(rr3 zVopZQBN^|6L4LR6lHYNVwT>(11C=L8%e9l))B%u|a*e1;sAjM1)@Mc{4lUQO*-5rz zDVFr<5nsw8Yq`Oy!1{Wcvan_qzq2QNY?uFffN4BD`xd8Xma95Ho z-I%crePBl8S8U_zskZXA z{8YLY)wyyn7iDx#?)G)Q7Z$jiztWC16Q>l6FiA$+J#4^&+?#nY zv#vbOw)9lQjjXR?%x4wOum7p7_7Y&*H9%vIy9i(E?6MS<>6qG;p zBe(T4s)5Cm2dx)G7q~`SR@HBzJ%_oZO3|!h#P!vJ#Cf!Hiz$smDwG}SeRYU>V=ZB* zO^oiiR@mSDIxvo~dTR4qx#5ROjDWW{5lX09BLf5Oi@%u8S4|3%$`FpG?V$p&&j$n$ zHzw)9{$7d$0dZoomb}NfYNpz&al9p4?=6``{U5N1O;1F7L(&E>Q{n?89DWw z9a5GsUb1itVTjmYt7?(Q01`wThQx;Y#Uz zvzlqNN)D2^?$gJSQQJaM4y!wAD4=wPB}wp^K_d(i&&{iToATg+3vm0b&^)_kjTn3$ zIV%o?H`cNCLp_2GzAPXTqG-{S98pFWk1qtiP>YaJM~+G$$F0WyjN*(TM$J|1UnC=p z$JD_R0Ug$*MsY0A>yGs{;i?)Y%%OTViS&ZfM4g4rXR8}r3G_6P5A!t9kM2gZ)xFHs z+C|=J-_QElB|sk52%T1KKHOTTo@85db*Vqo zL&XynM_ENH?udvqZL}1}@CGvxB6kjC7y4y$_d{oxq$N6@ACA`lOdGDV0d_6Pq52G8 zWWgKmtQ+zws0~lxDu{wy5qBhWC}S>ZY@7#sw8pgJ(wr&Z9pKf3+PvX+M?*VesWkG7 zO6v{>B3RQGC_+Ijpbu(2)54}gp5Q@^m(4shl8%Ng4k{5$1S{AxKi*CfOklZ-SZono z)k`)vdm)91^)=WWQ=;MiY6f>Iz!BxzJv2Js8v{2x18#2oRS=W7wxBH};gP)V?Z$1m z$47r2#SwE53;_H7I&RkHm*C-u^YnnM?~KMEUC#QqDLuC6T+W$%jJ#`7_ln4JCm{X= zwM`Q+obU?6H!_Ef**8yj#^py5cL;UI7k~=z`ie?Y^icWjp^_7Qhv8ip&6@h~;I%h| z$sg|y6dVtRfF4u0O}+?6qfT`?+^yjKF~XOli%8o7$PRY0rz}gcODJx94}U8xMwToC zw@WYo86BT0&x6ASB~DgMMU9Jd5mJ=s9IeUjcRo@}UJQ-L-`id|;3|sE!d+4Rfze`! zeb7gX-?He*)yx#Hl*A_$@{Qnp>n8Pu^j`w37Wi>c0ty21_>Tnn|2ch*$=-1S0DZ+J zBlNLvOT3*`3>?~D^>Shxa7{tb&^AS{sE1-`@RVLp{aM;e0u=U^N27R-k6m6Qks=3S zMEywS{EE7N0x3ewr9EetTmw#8uk!o)0>Cl`lH$-|c^9e6v}tMFRU{#~RyIB+Q_v~kI;>Irp^Dc`TW01iT^w?tN_ zs(Ys#WW(G=^nmWEyNTJM0g{A2Ydn9t1wOBS#*k^^cM#FK8ucRa9sd@X9stpnY|G?N zI+B)4riOMiaIaZ7`QAj=Q@`#O)eb2h`ssmy``8g=b_T=fgKWr?g^!TSm1+Xf-~f z-4SS*+97hrH4obo~S7}@Ri-^p^4+|o?w4M(lOd$A}o zG>m3hys_Uq7{=V-vK)>xhE||Ch)z+WT>T#U{5xIBnWPrhKrBPUNf_bs23w);e=!^y z4?X|ni%8nAscz^o<~bBTOm!pR3XY-#o#S7Fk0BWts_d7lVA6sRRobnGt!of01KC&> z`Y)6t3_y*OZ4*_9fzAg&@)SdH#axg-YeS@I5RQEB$9F_;9(b1M+_ z9MgKO#>aUs`&q3kLKzg{zg`wymfi?Y5%oR_5>Cyh+PeARk*I?A2kw*2At@IvPr@0DKskjH2fgZI(RGlZaToIunP4BTw#IoFg_NU3JpH zuzvcbp3GDIWcjZ)lO&36fB2z!u{#XFj4Oh}nk$8(mWRLfJ&$Ncbf+AUPKv?#5@Ae` z_!p7%a{yE4UQB%1hGO>ls%h_)rW73ygEGe&y>&^a!km;i0Svi&&S*{?ARuSa8EuI6 zkNfsuaFjTKtd>Ov+_c$om}L})EYP4*{cZ?8q-R^@igW1kj{D_89ATMHenPmJ3ow|+ zD)%XCufA=LjgfJe#X}T@T)2RD>{6*Lf;Jnbcp*q1u7^NY5>{vb%#T_ijaU{-6K~v0QM#nAs!JI=< zE%l4JR+_8}&Z40n8b`GY8gM@sJgbspUeL%wzRn#!o?e8VTlmC3|64j1+1a4KVXj-M zO-wxI5{sG$@r@K6YRcnQ4AGku_)8Yu5*UM$ZwcjZuQu=+!>s&dvoP69a*tRkP?5cu zgfhwhP8caL%;~TCu^ymXSt$*fCYdthaf*rP4%d6FzF7@zPFShdjV!SxZ8*fEgCIku zFxM>e%LKBH`u^M0C<~cI=Yia%SU>vI@xPdaZ%Q^uc1rPq=o_oZk7>S1i3J7Er0+XS z4or6gL-xmMen}7h0l`C0by=AlkSPVYN~pt z61ocGMm3Yc4A`uO-gyLSdW7MeJ33PVO6})A>O0!h-3h7>xNx_tBT*f_kvD~}%>+3T zsR!I#$AH%sQ2oR8Pk`i}2S8spqKXtrc&(zaf7W-vl z6wwdki(d14!+&<`v<@+A=H-_@%6tVcoo)hq|J;D9f0UA?F>ePklc~V#iH!cl3=!ey zOpplANSA@cY#3*D!F+j(J6yf&??{-x0$KaW7yFDW%U~3N9v}%#>ZN{BmdyMAYoE#69z3BE>GxH;fAC zgpEzMkk-+N$(RK`A_NoCYU7!WoXTZK{K{PVP?|XqT+fpuNV2BwSF50p6HNOVWsObw z?L~(`285N8Pcc?O3quDiTH{@@7PbV5KR_+p{RN41#QuP=KSY)`eoo9^a0dD0lZa=0 zSJb~$36OJ09=b%o$;dnPSInZx`(Q=FG2YQ2;z5u&0Ro=l>y2DaX za(8X0>Q(gBiL;kRM5%o(7fF_8G{*0KvdgtV745g-|C)En5ToZ$9wv};XD(KlV;!Qg zKtt6LHkbsJI1WJ9c@oeIQs668qTU8-ybwXaziF$a@aC5AXjZp z5ltBV%fe%;bPAJJM7&g7ARhGDrGDY!H9(bfzZsWHa&4%81CI6 zzq;H|Q24LX(5}z7ZKMP{LIBwcIKR?{A9CMn&1*yQWccn_cc*4kdC3~wK6Kw@qVfpUt4#x{XFxrBZwl_K!RRNF$LieFLPp zpYJ7qZn%-5&uA(RD|>Fr#%xTwn3WJ6R(9@srjm0inW!$cZ(pHLi z0WeuYv>*FR^V{d<5>HLW(aXNiTA=ONY9r6%;XdI9m^GNJ*1wlw+{`pq1znScr{!Q2 z@!YuLOGf!lY&IqhW(pW*H48YIX?V}aI#p@Zq7PrFUN*@%|5lu*aHem^xR#s?ci1%R zW78_|EDteGFsOuO3@f$zMVd@cmYpF01&~A>`IV|~J2^2c9*0c|@*X@OPU7|;!##JR?jW~=>J0upP&7}5@YHQ_ z-OSLq!E1$0mwk5Un!7qwbG*z_HostI;RYTox6djmj>gQ4e}kb(BFz)RToW!U_6OEq zG++eHrlyn7Aj8QWanlk|!6WCM2AxIZcW9_3q*WHF4E8tTe-m^K{3t#|vUR=?K;LoE z2t7c71|81T4=8^!hU^^DsJxRqU`4tx9BL=a+_k;~$6h1rZTs6p;yan^x79(IP(P75 zzvC1o9=TNVv)?1nocFBv)-E963)CqvEtb8CleNO)Zdd|Ak>OIS0*#eP;7q(8y3*$` z)W{>aP*&^8XHlRV`$hjr_|bnBkkUEu^OZ`(n>UYq=5!hkro*&QMDvLh#hLZnKt|Ku z4<($j&(0l;!$m>{-hU0}HE#)K)RZKmQ&dGWo7NEx*7UCQ#-*gFI6e_eYEY-gmr)RA z49n%{k@R>%xyxB*+-IMHoMKt3I%fby1C(dPqEMKc@{41q+%;?3y2~pEfa9>50C!|e z%rw%Q$u+m=3wwlqREw{(PI0-6^}z3VQOqeQM7I0|CEwsX5QYo9;rBnkV9Q9$qeOz! z4ps*ca6aqG!_DwNE44HzuIpNG5?<|k#J!(f6O-c8_j!o8-#M*iQAiH3#fY{sfKy5{J^(%RB-7ucL84vh#6rOITelPtZWN)cegSs7J*p+F+!! ztKsE$=u3Nt{`!PikdO~hn!pTC9gA_8gkimZH)ss&q3i>O@JT&g~wLv zcTjS7VJJ*3o*^8U!}cjwvvg4SD@3kQ+2*}yL?g+|%^((UEh80LauC}+4+DgZ_ z|HSn6#0-Q8aXJ45 z4FpG^^11DWifwh9U~R94;ns_vtY)n}hW0z(KO@m1DLV4g^qS`-=f>|u7jVMoX(0IZ zXbi%3T#4UusCa&7`Sc2ij`Q&=*cT;m@GCg1f0a79-DUr)KP2RGM=7{kc!);8!(Ftm zN-*Tijy2}QkM-dcj1)v!WEx@SO`$tR?QDIp%A&zl!dY03lP13H?ten{B(4uMXVUMgzNG>(dE>q)^95Z*RJO3AqYhLi+-tjZ- zLWR!VKwH@O6ji%&D$FHO^L*uqR-O?Pn`6HLM;{e-*u+AP*+N{B9~)+Eta!lbB5C|j z+)sAocrgxbhKv?+WH#GD7B+mi(UA1)&q#3Z=krH*TX4W3BVv05neNc@(d18d3yF)v zAYkPL#r9or@-zpu1TTC&2Kq9jDT{;soQ9-sEzP;g4k}mivz1)3d+@^QIM09;y}|B= zR0k*2;EY+rx?QB$Ou%7QjUrBgk1er{#buXpLN<#N4VPSdn$dDpYPF5VvVBc;oqn6M z`BRnp6eFMt?KSP6l}A`{8UrPYq1?Q(t zwhGyvIRoPglVUEZeTegQFkMke%UiU%wP-{?j}2h87Mtrf;>I>49%rOCaRa7_WywifKx+Qs>ZLBOlNPMkH#h@~QUgR85!%AB!3Yl2a+1%c6*gkp`Nq?DvLd>Tm}p zs=l6M7Gq5Jr4^1gpk*h@f3m$bFHt34RRSss`rp8`hFO1<|Bi7T$jl^r2nVIXy_E6U&~lVzsiUJ64kePiy=)(TsQlDB?EuG0;#$Q~qan_FNQ+58VK#UdxNf)aMj7pzGz2KY z$s=J8bB(YbD3$dMCFilR;24wUmu^ znFap9V`#Hj_Fy;Ay~yJcm9yGU9Kc|Gb6`fb#}7YMa9n!pL;0<}>>cm)Wa6pqIm zJ6EVhv~Jo+Xb^)xOJE2W6DN@YoZz6QE8uqi>qnU~uP(5gCs=}0Y(;4{q@&aIJo}44 z5$+~kPNF%U8m>p7iRTh)N9Bgj7=uAU{U;p@?;fH<14Z9*9C1V1tL4v1OV)^HL$tb_ zNsXPTH_M?Q0x)T1qsfXLl>>0(L-DvCWQ_vPQ5}PF{v_TpkbrkgDe9mR{+eXRb%goW zMABtePV#R+LbR9EkmHDRq^fTha=3}4eTsm-2H!|!WYiTWKp%rc{$1T^6nUzs_ac<_ zD)-zuoy0J?D_MrJfo>U;V1yCegZ7quQl`l?v?ZM~*hd5n1$53l!T^Hk=Af-_y$tLvqRf;g_1hF-&@Ww^dIB zni>(~FX!%+1{{8z<2r@m=2t4Nw->zb-!+v^mAvZI4H4Vi?zzt;6CS}~Y#^~u4K)o9d3Kk}{$>=hZ0|;Ck2}BM#(B|Jqn9YhjeGS>BE}M|Oy>`v)f8q?)9>iL_=SSZDIP-Oua9}bwH5CE*QPC@r3O9f>0FsOoK5L#o6&!Go$BQ8@e)VnKWjzCtvF2w zDmHRD%PYZejzU+5Pg@u_^And40r-3DEyaX^c;yvU={@xBcoBQD8sC^-UM%hJ?NywP zIh~^S{@B)Dx+f1Fy$nA&eRCKEK{TD2wh;hOd)~0xA2q3-x0THh76V}$z+{1;vN8Qv z+$~%0#$9>X5nDlB@oZH+7i1lz?)dTyuNv_wdPq~dB5<&ktq@=CZ}(??yPM-1hi%D$ zarO^OHI{Tcy`FLF)3D!4f61E=Ni>~6Mt{IpUya;`AE@vIqPSB;B#hyOPMz?ECI$m` z?xW6+;qrzmXgxFMc0v}qj+OKI`U;>-J;>^@O!1Z%o!xg_m?HcIxXrl~NJ{7A4^(}b zdnXSc9*sa@>PQE~q6@Z9X0vxgq*DpAn*z}T#H-)fiFWnUwQUs-i(EUbnp#iUqgRg= z5|V1?uA~>_H{)r1m42RAmi!LcHjo1p((oPo9KfM?^D+MJmOra}!}bbm0D|F?P`lW@I$ch)2u)tbSdf6kjK|EY?3qNpfGO&qhu}bQ@n; zC*>leMIxb$zx|}KOSPP*VA=z~dSk4O-!$qA_9MPQuT7N$h2sv(YUs<#qCO>=lU%%= zgb4Q@6yyfE8q#~9SO#&Is56b{R4}s@4jq#3Orcj)T0%`QlI!cyK+e);-ai*<^J#DI_aEr+ zhY@Cn0V}&k8=qhu5sd&A_R{(r`!bpyrCt5{dz({gj81bk_bHUF_tW(FgWB3!%}X;t zK>H)I1MZ>H<$4wKmLIO#+{b~*uLxUAJg@8 zvOoTrBLxgTjR|eKYR9zA)5_wvve-u$E3#U{rp=Wac9_Yr5QU*p6w;Kk6J|Ih!p$8= zuP&&18r24%Tke1`L5w;m=8Y3~&~j1ki0Mw2O2#*iicC2iLJ;=Rbc=z#?|q~ z^h>iFi_&VafhAv8mN4z>R#l1XCoj@^MR+=(8XKO782vl22*kp9(5J2cl0%153u zNF;cz+ztU~9=mrlI_{m^%l;jVdeX;M_>zrW5fiw6XAbDMS_R%*y^;hBTLloQ-tk+y z0(Zf?jTUN4(05Wshy3B;SU9d-Xbgtq)di=vCisnS%>RZK=91O#WBg6g-cLTcWxGy{ z&0LJtj9g=s`AdK2#q@C9DE76H)SZ`fbTZ8C8(|1=n*MVq7d3|0QZdFt=7n+ze)zN-I7$82+|7ti_)MqHT5uB9{)7;~`;MeWvA&p@L0MA0gX&UP zfkqTyGnA#`&S_ZXvjNws*gb;1xgKGC3`Ct#ibRx zYr+yB`T0#3=2%*TxH|x-V2e6=s|SK=+~~in7_XbueJaYviyt-6ea1AM0;V*iSrF?? zu`7*h@xv@|f+VWHLtWO(XK#MJ>};=%eh>rv%jungC2fzl!Iv_cLAHYib_@(oGc_){ z#5W2ls=Wq!s|iF>CHY-n#JETWk>Xjw*?*3@Hvj=bIw`F>zVmHV!f2O@%}XQAhh+w8 zoE7J9Ae<{{I?NdXDRT6(KO(1+rqr{Bi(YEZskfQ}D5CxL6tQE49^BsG;9iidJNf`k zl<#;tx1M?<9T&GSSDvBXUo;CR)Wy$QlW@fg7P+hrvxv?2Qn{=Vs^!!B!!*s&y=rf1 z{HiU7w>nT0%4*C%sR#yA;`ar^LFuw^l2q@zUmeTp{8cm?)ZYe0;xu`%g!L3eu{m}m0p{3Tdo}wRadQD zd*hXfZ@s$KoThgO?rb5Hn{hYR8CGn`$$xo<8V9N+pi`R9{epB2e*wiozB@`GZt zVEZ4$L_~N@+iRPC&t7)|YrU0uV}WIdN8(7z~~$VN20pj8HoD{%>>(Gzrt!^i>b z5F%FA@?IIClqJ!TY}}&e6RD#mXJy%6k*`Q@Lq%@JE}N>IH}U6Z1RLO3)56i29q}Ez zolFRxI;9wd>wAb1CbwCEb4(lbB||9VN*W&ZOp}=77Tg|_a{0T z&9`A;)jGWv`<-Fla9s5C=uT*ch}7<|C;C`cPVgi$UIMq!83)Yl}0suK_y2m#Ac971cf~X9t?*jQH&p6!@LK7 z@|}JtC`Aa9oKcK+!{CUcGr*$zF;wVSc)Zv~Nh30*su|6(8k%bIZ>~YxKoj5~^~UkR zCt}GslTqB!6ya%5$DG?Bl5E60<#$44MTORfP^x;J89odA_+w!V=Rqwy9r7F2q%&FN zuWS|5joe2+g3VDFKPyvwG_}Mvt@c4BHE%D5N=_S66*wUcu^s|Hw@WwPKa%QC9V2p2TqS-?{@8`x~q^{!Gc~bvLk=cDa9_bMIy`Zi_8x0FMHgxaLJ0iU-bWQ zb&lPYK+C$0ZQD*(Y}>YN+sW$Kwr!i8j?=L^>e#k@`<%1C+&#wp2Xj=7s(PP#D_ZV0 zUHZu9FURGkpupYm*hA#~oDq@yEJhtU1!OB*-J{_TfeJBV!QwU{HKd`kB}YExNR_|P z&S(|98Cu4c?Wj)J0YE;SFZ9vql*!MqkLcYrulaAVqwOuH0~2$V=Xs=Vhdp)`obzZw z(QLNX1dF~4h=IA^UdDk`s()=J>;`O27u=w9Y1moLct$RqQ*SP*2xf8ZO}3GsyqbW} zmRDK_u~vR3V>I-0Cs@u{5zg`E1+K6szc|)L%&TK$gcMp_(tuRL3BZUcCO`9BaEN8` zE$<^9Xg%j_b?9T|a{Rm8p{&uT+@jcp9COJ^n10BKd$Q=xQ1VWBigH*>$?uqLk>BF= z-p$jI`Nk3R5G)JZBF7;H1h0fc00NJA)M`mHgUj5KNBw2f@BgAB(kK_pyFfuea3TIh zGgC?;IaZ1yCQ@dGZIoGNtlsA)gx$C z{(>}X0#|Au_5%Z-lcZ?}{Do$?2^|*3z@5d7*llL1>v?9@Xd4LP9sLvJzOyB=2lQ&U zFF}DA*`FN}E8nJM(=AB1CV+8=@VE-C6W6X}D>ecsU@>dXWLA!P95pplwq(Jt;Okfj zA9Rz(GC^e3OoK5r=HmFSvOU4BHcw42MQ%}o?Q;b;wxe#l=&`_S(NW+|BTN;A#}ibi z=}#&&A$>eAmsd4IF;RLdWnk5I>h<@UhHXjH_|%9d4Tq;z{YwfBru%i3s#+Y*UZ3iq z(!2?Hj-F!fBeGoO8p8j0%REeOA9mA3( z5D|ovBT;Q8SKa4iW(B(E68goV3=_ z^VG6r&i1ro;QbF4QO1KX`pF#xQL}hg%ri28E(L`o65R@dmIP@PzGr``K$I|MW zm4O>v;jZST$o7IZPLJ>vtFeQyuCaO0lD0tBaoi>mLSwQtVK<67y*%O9gl-JRvZzP|g!Emp`-j{qKZeg?RVPv>NB$(-SB zcf=YKh;}SvI)Nhgy0!L9;=iybpCa*Nq^?6VId#;uJh|yy%vLzLPd~lU7(>)+YXze= z{j?=wLp|W;l)Mm=unp5 zD_yguHdGb-w0St=}|YX z91C!Pvw45Cf_xac?^c)t_{Hg4)tyJ0TQ%Y6V> z5zv9SHKrJQ<%h$F6A?rIij@Q-cY2HlvlyjrtUa-i!y*i^+4K~- zm=2h_&~-S3R0y=YmSY~uG7x+oIEGs37wsU#iK>#qU_Q93Xfu!+v}FwcU?t3rp@0d- zHm`~Ea&Z}0yoL+ zl}VMAJ}gWK(0a@I@0PH48h;5ao>PFHaYbrOTnz0N`o{vFxVS-LU|{I_|s?H5u6 zg~;9@d$Z6~=|p)Ai+b7lvH3x}h>b?4&4^;|PzI(Lu)LT`ATkJxDJBpl6cQ5`5EO6F zR|$fH?Q3G+gIat#3T5<9(fMt1MAVH^Y+(Sm3!k`Wrk~tCGbCO= zUHsg%RQt?4a>K59{$6-!VrZne zr(#zo?pAq$_`_w@(wxqv)deerp_chd06}iSko!Jkf&+`-fwc)P~s67pWOx#a= zgOY^LU&45ggaN;ay2~(aB2jUax%1SkXqIdfg)3m6SitB+<5MCfTUeTS*t@5k;}8MMG`7|7H88#$Idc$m6r{yOi{`*|ZDCRiH8B>J+lATLQ)Ou) zHS;LD6xt0uU0Q;^5Cd+im;&ahE13G+|A`s$@8xWtb{~($Y@YnjXo2o<+=MCPU0lx_ zZhhB1#}}Jcvp|2a9e{rkdDOG+TsVu#XxR9v`Ame1$e2Vgu?P?@V|c=XP>UILfTEoJ zfWyC#JQ`UnBb`Ku7cLX)s5%@MafN+~HPpUC_mD_TYyPo%t=dY{KHuPZYDweDB4#1W z3`VPSx~6;G9ex+9bd82yl{IOW$xrCU_{yedaOgD%~ev`OT|HR9?UmE!*S8~_GbyHl*RLGVsSJ-{!y9SgzppcD%y`*je|YfKP{aWlon zg@tBt9)KIYbtYT=hz!=+82JgO+Q@~|&Z6~y-5=Jv!uR#){a0vFGT8l1chol6Z*U!L zUvf#Gg{l>cpKmNPobFlkW_IXXxk8e$FwgiOY>Famd%6+GrzMlE{}>uZ0oQgEvyP#j zco-))i&Pu3 zSnF<6nZ>lJnD_N3MWP}PiOr@eYu)kOY!3?#nGm;O!J#KO-Ct{lgzzZSEhln%~jp&4We?DUI z4%n?At50PG#v|-@HchqF0W*({bM4Ue%@J?W7jXywAn)Yoj83=qj*L<^B24xG-YT*C zh3mqCkbKWFND8AFZSDbwxAyC#`8%iai_~LweikQO8^nx(X3Zj!t?05De+*w*&T}7! z#7TGt>adSAyGA+rmQ%O7OPB0NAL*3^Q=QaLt zNL7owvl^%*4L@GtLXvx6_-#!#gahi6an}H7g~7?`3qF&C2IG=;jhes zVsxJSbMEGGuD~&m)w7`Q*WxUQVu|?COgYi18L1<|lTuAF9*Matr&~ z19XJxn+kdRZWi7#`aA2`G8DMY-wnh#@mKkC?JRRi zGU3XyD#R6z*(pX#=4r85oIv{MKb!(f8|r`v3cW=2+=Iy-9Hi-)=?!g5?#Jf9oMMV< z?BnRxKLnU{DA8Q!2%Bfc7o0BFNPTV730}rgXH4>Hnl$ePLwe>7K=n-(HM*_jO0k!Z>gZIN! z0`gT4vO(E_1c|u95G`{05Vz#1p~UXgB2M*v24kfB-}SpT}${PCz(ZN zVKZ!#A7kDjl0?6u6n6mGL)9(#L|>Euc{hNX)C(WM8x)p|fyc?n)bkt>$sNl4Apl3r z!=0KN(PKDp*aY!cA<)Y9MJx6aJf>r?Tq;mZYw!1i7)5%7)S0&h{Lg3FRjq4i*eYYC zd2Gm+JW+p9;>3yvMBnh17x0=Fbgvt1`HwibFWBU9<^GzJk#%!SvIjt~7#ewwOR2PK z=pVeQ^3!ja)?;Rm2m9|Y@PrU<0$XNg87R^bElX>7`+w|ohZrhig)CmVZKE)r2xp}z zW8>7m0?jpP^#;zG4F==q2swr!aXHh|um75qMKr3vZT>^Te*8niNdFVdFu?!ouBUZj z{r?9H>zi_QqT(XOC1H+arjvVuAu|S3K|_NvACL!wQtzeU8t*r!n%OXMse^aas99RB zt6y4JF0-}(lN@0zZmZi{P|$mS>RWlz+5UPnba)dw-dam$S$KYXZ~K_)I`%*2J6_L7 zdHH)?;FlDcem8qp6$%VIE=o9gCYl;$VU7yIoVicTAtdsR&V#%#^#T8C$ZE86&MJE!-kCn_qtQuRmKeT(kt% zth);pHv6PZ&ZjOY<-ZbHq;g1gYf$6b@`4qKuZLksy=uS|uE}DLG9<~;8dYR~KnUkW z*DG`ACh%tnAPW4!mtjysptF zZDCN9fw8r_D|n@~hT?@l!(VxmI3beeRoyFhm^d*MJl0r9q~arf7^4wiO`x`>&QpKq z=;E9(=!dyAR@xRmB-u(^I%X;vYxAXRCY%s4)s`f%s|*ys-o}VSkc`u=1>mqDlCb)K z{_Sy6*dSmXv}{!3A_q}CKV4m&?QRn9;<@TIDQy;h9qqm;J=hxlQ(b3-429=%jPbY`U z>|7FQ?F4346*g6rm37(q6?)jQ30n-Sw^r4-8ECnYH2$;^cyWfIXX_G68W0({k#R^m zF}^fbzedJw^DBP)9f?}!kdk98GtezY%!z`S>A+dsWK1!o&d(}ybEg07pPTRO=3-BL zG_(p@jEnI%&ytqX5lXD>@(m{O4t!vs(Q&lIcn3Ijv8j>5!Hv7{gD-k8yo(xbbBU0E zlgtIZxB)Ia#1dT1Yz?Ei;P>NUPFAi$QlQuk5duEp?Jl8YtKK#$YiJaCfUk865n^;3 zqI>VO2$ziVRZyLi9dv7y6aOM1*Uqz`Io$&*VU@cL)K#o>ELo0sM_^X&XcR#GHOry_XftnI44AJ|fR_cKp zW3UGacceO3Q}FNDa~gDM+h5ZJvPqZoza4>X0tR(YBLmV7a?Iw^oAkcGUnn57%=nlV z#oLit1C0S*Do;8PZueV)X5#jH&MwK8cB|~gCIX@0x0$F0Y}Tu3a4tW|1(`{zg}2%z zQIN(WdJqQ8gK$|Mm2*&u*dtgSS>IAfwtoD{VxUq;>LdwbfHnBhu$E=tQN$gNdTb1Y zBVdipPu@ZjfAhpG&)Zd-0-q&i3$&5#pXua5<0|qIBOdiMWX_efS#?0Pa-?Gk=s$@H zr#fk>gcFu7EOfs9w~LG#x! zQw%lJTM^3e4-QO_Ze1I+|8(MS8T}Dm$(DCwKA_k%n5U&xt4>0AFqoYslxBH2#a=Xm zc*g^syro5MqJdt{#*guO3p$bU)0hbN#Ssx8raBzJ7xsRI;uKk_1&Zed+?5e#S2uK5 z>Q>CeI#uln7G9wGRCaUNzu32dwYLEOn$d#Y^~~~Pnq$1}nGTx|oj2uuzTpeSF9N)I z+Tpnq&9_*|j`=pcO+{vlPmJI2f<-dWLmxhIf^uHg?p&LN^DXW$f*j`A^N`v(RT+&MkqZ}yM7#f3BL+&KRh%@<@xgVu>8sS9#s=O`v$dtTZ@WcBI7YvPq99mjn;`l-%o_m@6z>NDv z7e4k18&_~p!TyCuto~vXSFqb)_rb88&7LJ4kylk{c1IcZa6NDKRVe*u{w31pVFl(a z0z=W7e2-FJW!0y9`$CXFzcp}!4>`%W@o)vd65vL z3(r6a`vN88J#DzpSpLkE@n zg4F90O%PX_Vc8DP0Uyf7SJvqb@S@- zEx-DiiZ(xPZsvTj?!ULF^$7)2Z8by`J!H;DKn)bkoCQlaSHHRZ{-x+!{)@Pe2=OWs zJ{Rx1JTb_hDSjkaxk@OX45w1$1>QBu`Ub71zY{>k?pqL8fBXFMj`wTEiR2Z&$WEMQ zg?-|#=+-3=JusaS2nUl1`>M6y@#3%!WSeD_&ZB9L7WEot?NOj^VW;_s9~Igm76l4y z0+#4GzEHop;hB8gedB!x4zTBba`;7vaqtE2er30HSLJxSvg^!}pPG?(_P1)=iJMX6 z^J1I786f=}{qPGun#1sfAN|;kJWUvpk|ZNpyoR@O_7O$0S4%q0^hHDb0*=+=hVyV)#qtymPQ_cO|4Aj(s*d@l;*Ga6= zvqRt^u3FsoegPTZp|o$Eo!ZZnakax?%9CYf7q}KU&{CxaJrl5VY)Up)fraE^Mpr&ysVbI-%kRs-QhoALgdS>GAx$2YONaS zh?hXYKSgD*u!J9Vs*|~Gnac_n7#>RZ#9Mev$9Q9ZmiyD%OTZJR$6R<)EZKAooJ)cW z)@N5Ws)4qw`;0}NWNW1>2=d}4-+#pco24>NObJ7PqVO@UjVUQFYieHNY7UIrWU%D| zHiJxe{47JQJ@CT{lINLW)Ypkug;Jocx$WFGQ4egB0=+dtIAJxNQ;`n?7>ajgq#tH? zLo*rS7C)_q4N*53a!)_ps5Y`5WA8-s8Ta?N4MW;PuH?R5Pf~!-8o~Qd0ae@eJd+1* z?b2Jo+UJTLi8(3FkLd|z>8ByNURGxSLBD(-`tF~)PCh!LwEAX;I8&Wm%x2dblt+~l z{;ruPAUquz1CE`77c|#-|1x{%`taoy3+XwH% zx2L@GrKI;s(JBP7OtoXpNNp|R;9S;3a=-87eM@wN6KnRTd{}bm_v#AZ17e>F7G?xU zRj_(|z}@1okTs=8CGgh@xIvVPif|o&5&StbQ55T-)}u)$1Rut6#dgRP?IuGL7{=aF zYeV-7-7qO|s0W&C-efbkUju1ZXnFVi6oamagvCIF=x(0F9dPs>MUzlJ^yb@5+SZqJ zG^c=ju4ESAHu{Ej7rjDvWO!?ww!IF#WZKHTi^1l+5n{T%9>kkfo{9nKiMSf^Ce~d4 zt)S>%p`q@o@n|x^Cm*lkDhNOh04;$wDrR%G$K6cO2@6w1o(s8a@L8n5XRr!R;^#rH z<)$c#uon#}O?-Jbl7TA9no)68plAz@wke}%o8nC*(@6f`XPSb>Mp}Rl?BJJAFh&+% z3nCo2Dra$hj!$0DOd@%NIb>_oA|y@NapIwZlxIp>R?!Ivh08)y4;^PO*ShKB7tU@2 zd4R#>vz`pP)uKb*Q>-}XQoqwyqN^(oYt80V1^1X+O9l#6GL=d^NchUTc1HDyL*HoF z2n6W-J)*x0=f^*<>2H1lUJY*TuiB9vOC4yOz=q`$RJgj*J*2j&N|*5S5E6|QT_8rZ z1$_s`2uye|XtS`MCX;NAhIldsQTeA1EDM2vS@`)M1z(^vf# zP_uKOndp;hQV!36I12bBK0h(}W$%$wgaDdJ=DYgYa-ei2MB{xDjT@HVE~lwJZt&9H z=aqE}M6TLYRkCxmu)H2}Vai)Jr&fF+ZF3!wa>v%v92}!=gLqxGql?=YXh$70A|c zFL(ad@8E(GfdH>g>_A0#(uY7)e+6hw;^`7l^JE}twP>7(7LVhmQU?NV)}R zca8w*l^-de`XVbX0E5}d6G=lEu3Nh9tXWA5G$MB{eu?3wm`EJR)O~jh9!LNPYN;#S|Rrm=_9sL;sjysje?3y~K;g0y#^I02weDx2(o>Fhl@Z!LLV|B=B=u4-qsIbG&7GPWM?xR#KK* zw*h&!@;l^DN#hMP7cuAsY%pM660-v8%^DX5#pU#nK@SMcS1=L zYC`o(KtrArV?@3LQVmf_yWyWc&(XP{0>uye!P%~tQ@pbNfp(U&(?`d8f--=VMdAB= zt-IA>eh)}jj$&BOhEqnJ8tG%rgISajq85*-6)9KLw^BJi&cAxjlgJlM5~Zr82n@(R zb6y$llmGOj8C(J3@H2xQ7iAp@qsUs||2o}F}A6Vw|m0R?h}*21j0FSfs!&aVWGVGANW7*0wUOLT0V~ump4y5hK0Z{2wXyqEzl++chk-D8ze}OS~pF$rx4h`I>%^j zSUCfRQe|FR!J@*euV{$G!{d?MJjnqI#|QeW9*Q>gF%n;)Kktkm6ePO5P_)DK!hg za5QvvGKyHX9g0BjI^BlQ5;p_0J2H~0;|B^1MPvig#L;Bl71d<(sZO^MHY^@yn_qJy zC>}*7yp%nJilJ)G2alW*I~WRRoBXo*C~A6AYTL&T^X)~R${~^_1I8`#)asdJ>I_^1 zY-}%|3^i+Ir3OZ0g&X<{a8JT|AbmFlwFDy8ia{dArSz}Cy~puLFls$ zBix;g0|}nI(N!L>WXIOsLDA&9b-IU^f3r(}F)a+30X2^`FKp%e$EyC}<3zkW9FdLd8d~1B#b~zFq(JnM3c-RqZ7I#Xn>l3lnA@dwW{A0A12 zgDifkjON@}Zu!VjUJdAF-8l66`%#*DOHuB5QzMg;ZcMH}k9%Wp0ZIz$r1u2)d$k7N zMZJMAKw_BP5K@0>Np!&}Xkrr^Y6^e#QQZxulnCOK8y8q=N`KM9w@6zCj@nGyixoAl zvv4Zr4mV|iVo4ABiE~7-GPKs{30+X%U(2ZYL+<=V?}3P@Xii*Q@2 zVgYeusz}lkgp<=UdPuB{#RZdc!X@TR#}dc08OtC(GB#8!=%Nj}>vKvzj?FU*KgbUU z&D>(a1~sm>diiFf7O$Gm+=y&N#Yw}ZWuLtDhn5U5*$A6tZ!v`m4qZcz5Nf%caT_5S zU@?P+RC*ef*1SM-J1BsYVmGD!qAD+j0>IRhm>N2+$jT8#Zj`%Ac49YBx)7hY9zWWu z&N$|(+7`jSPTs)E0mygk2v-5OXiV2cw!19TRwJNasv?|682qPqU&>Utk^hxx zrRZ$ub{|uHy;;hbb7Vjov)rpYbNRChoI~O`Y?gjW4OK%UBC(@ZP?F;YIQs}@I!byy zA=|Pn3sgucWmcy&$!w;dLO?<(dknL-*JUZT#s&XAn^+}(*2d*4_Ys*mE{__AVPBuh zG%16X(eqSOhi#)vfmX7mrL zMmkQPNb0v>#_q=kM>wb7{WV9VeL-mG*l&R&8VwDey}j|-dI#&P+>v`}4sO_~LF+5u zIp?m}!G9?amBR3cPoR6@q@wVb8t}Rm2ohG4Z6k!-9z*_J$qyp!B|!gC6iQ6{!s7M` zA(VE*1}QYggpoVOg!uuNK>NZ03@q8{sQvbmMzQ?MA?B8ucO!+`abZSr;__iQNR07; zszmdG{#Cof^g@rC0ZK($Jw1VQ>$~WB#&%TaTb&PAxz%KirT|vtsGy){NiXw>&-dZ= zAvTbbiBg#pZRj=X{!q$En`$P(cyU0&lwYMS<40==QJ;&-4z^-o8g-Nc%(pZ6(;hP! zls)rDGNMFfzxl#HRX+xL!H=D6K&0T}iG5`{@hb3kvS8aXDR%@!XJu~I!_L6+E;jcs%P*}2YrxsDxU`0xiSFN_SWA#Ug~ z&~3wp5{*$ira!O8 z*b>a^rFf7AJv=Rw)d4Z5-Q}s=;{d#Qmn^`M&ba91;CP7=l^zO-npC_^>9KFUIKx6l z2TRobvL(l0kpJ@*Wq}&s$f5Lxe;XxA5>I*2;IGP=L*QcG9aOCuIG&YR|JU7RkG|K# zo6N3X<&F#&q2c)&Fg=HHAYF9WNOp3P-r58b|LfYSl|Gu_uSoMB2u$rm^^|M}jMw;^ z`dmhb%noIxU+%ghPo&xg(@La2j;6b^h{Uhtoyfe(t&;c_d!ho#-%fyh`AQpv4{gMl ziPnAXCa*N&L(wYg?CkM_D=1G1gWD)bv1D^7NbzK=%uuJGz~b6|cxwbSA?ZbUo7ysg z&^jgllXPtJV>ia4G{?+Siw zcSJ3JxiFmR0{MfBa22%qZA5E?E@q?9_B&anblosf*)3f-P%Tuh2?ZlYB0jAeha(!d zQ#=)%w)R{Y96Xc?=;!cYpl5b;gHY}F8qOgEn8fM^&?r$=(U6jJ@;P`Uc6YebAM?E} z$*6e}CB(2Mb%;L~ccV8%!YbNtA&}ajWW}XqO07uYfekvRfPgLwx1>R^b`5(}+TOrq z5`y3ByCvQX6`_r8jAgA!M|w4<%dI zrss|fMK17Uq1#xZPSm>{5zK7~%IiwjvU4-co;%#T=boagG8>_bC!;0ek2s!-=$+U~ zCI#A&K*1)W_YqA3ly&DA?np5**f{p8LCIg8#4IjIF1IiOb+cx|{744;Q6jfY2vJtX z>JY|VFM-aE{G=#4(1_%QlOiCU0}3-Qt# z=$-)M)xflRo*+NvnKL|6a_YVIr7Y5p#Bdo3@TZq&WO31gBHID{Dm5uZ(Ywu5UAKt- z4|0kJqkb@07TDX0c}|+5)9ubzA#Ex3xyWgyU?eT4A{5GAH1R(G8D#;hrZ4q1Sxx@n zT<8>2YXav}4}|V}6oh96*pxevKXZogy}um)UIu;q7a$viEA-$8_D_h%{fD~$A2^B3 z2m_RHbaOYcw->XvFthtVF)uCE;D4-b!nbWY47xW(>$YDs%B1z+^x(2lMsQ>zsU(#vNGS8p46Zr} zmF(fRj}di~U^P2?*BWgdW^FjF(}?O#nTcFONdy35tw6>Qy%wmdoR{ zX^ypoF{}$2$Do<+;nnA44pRcrsZ^;DC=@nE2?^;D+_2rv_n;gnZX!uHpPwxKj8+}O zPruFnP%R~uanXq|8A9Nm{;@p zvUY^3an@i#SUaE*O^PGIP(%geLR~YKUM*&j-N#5PpqVKUrcYNy`CI@FnO8z+!{X@) z2Lnu#b>OlP%`-;7?k`|T|H?dTx3 z%YX<;2X5*4{Q}i^H?@h_4*3^aUN1=gJMViKZ=6aqHS{qkUJQ&1p=$*@s2(`iDgUemP0Y$wdO6 z?3!DCAxNL*g5!HIp`{y99|MYMQybBt6B4ag@2Js=@ds6*faHwvoiTr)KH$?;Xypcu zcx7TrHtEYMlxLJhvPan0i^N;7xKd)e0y;-z%T<#oEvI~2&b$o21WpY>u zWp{jDl)RebzBs=3&S3|l3OS@FRTi}0nG=tdCdi@RxltEf?}rwo*dMw@cf`o@`EO7L zbilX=jq-i|A=SLxQ9>%|cvV}_ue`1J#5kONc_rJTRI-{li{a=K-=BS>rNu|{ue#`# zXYbokx{hSxE%k|Ln0t|pYcO3nHA*@xyEvxB z=0kq__LUp}lKD37w#lA}mNaN^PmC%5#Fi^-C&XE6;=u3Lx_y;R})k?SSH zjn$scnrHAq>Ko8WHHOt=j-Jv(wPnj1SBpG06|Ua8CU4KoOiL8mfs>>lNycz}D$=op z8h%X0=h_~Cc=`!|U2L4f+$|kxT~!I0_C$_o4_jA*9fAXnnQ2hAFAm+xHbr$7Q+nlB z9dycwlxQ|8h32T;^|7Fu;F+W(WN99bK6+@YX7-de4P~+cMa<|X*m=pS8-8c~d2z$3 zC+44Gzs}Um=QPLWwj1=3;7-DnlOd_alCI$nv| zuKd0o`&Y1}ANv>CV&|nL*~W67-N555ccRBANgXhP?lLliU9sZuh$@m<5F3Gh%3O|Y z!{&W;6HifiU4=7XN{a4$XaXTH=b_pgBOITL*|?jJO$42w)n#0`DMQodqb!hPakpkz zHrnkN8(HHbGn%})t@4tcd%(I$RZ?7pQV3UxQdb@mWoW8iv1No+Zz-0^)C{c}D(^P6 zrW+_V7hFc(fuvtOZ)UuJX(k=oR<|Do+1+kGQ4AK ztIV#{$W6-U7&2jR;DlG_$*Q1Rcbl3vQe*m)H9rzBy$q|9Tsp9DaV=In-)zbwse}z6_--JMHkE1~v+q^%E@z_c-h3sh*vF|hhEi#X z;=Y~9g0rg|ceoiscXza0yKtR%^8m`uVMjKq+JeL2fS`6IrP`TyP^$NRo4ascD6Db9 z+F2^K{*NBXhW?SNRY((S|75e=L*IV0(OPk@W!Q=SRoy5CO?tL72+5;HwQM9S^F?6T zutNCO-&_}&WKj+V68r+O4$k!G>@|jKRkZFfZchEg@$CHwxMal!w_F(jEnoHtTE5Zp z3$O4`%B{7$l+#ShCp{`Ia9(b@lqB?`k&wOo<0UG zrCEUK+(6o+D2y3sPf0i_#x-7gF>7ESimvNksOxznLLKB-xyO`!T2Y&_wMH&X9pEzu zd;Ewk!R$WD@~pSM>r)>KKBF34Qq++fNiHQ@;5>9`#1UA+OS;gMZOEmTe)@nRP`7Aw zs*y)j2<`C({cA<>dKtAK-kKDUQcl0l?QEK(aiSmXscSwV(MGK&N*Qn8= z50_EH{mLs;oKxyQBCs#ZY5rBS50c{~qA;KxrAOg-{S{xCR7;E^YE)whlP1^wiwX#z zMdrmx9Vr6ZeMj`wKC``hefA;n6+Pp1^PJR}JBbqqEWAg4Rm^+7GvM8xewJ=gIwtB9 zIX3i7I^9@I>mAroCFd@o;Q^Ab;&G)6Xm7w3@3qA`GguFIH!%e5^Dy!_TQ+hAXhPR{ zHzHDt%v}sN5uGB<%+#OfN70oTb+%0(n`j?@`U@ZXbtxSa-x|nU5o$!TUsGrghs-BX z1- zCiVura~7A4b3l*V^Yt<4qd7n~;_Zqhy&8vB9ieg**sxk-tt&842MA4S%q&&p0}LpN zMQVl`=Q0OyF?K6uEOWQituQAAk}I<+U~Ml#0fK)%KbA;7K}0?Y-GU@l3)! zIH0RUaKcfN=ib`A@2q!Pk3_FIrPX_5Ar) ztB=|lA?*GHw|ayuFr4>!;9)XJK z3ZFM*%KOJ2UxdF3?@h+@_9KomTVZAG_Nt_7q6t#RBM0R32re#|QbQbW#c60>k0s)O z4fn*uEV}$WY{2knmHiC&FY;ftw*~HjVc)g)MlTJSTP7JuJZX;aqXZnLeO0oU9M7Jc7^uRJ3M?d zzH09IJ`4(PPa;4TWA|$#lmo5GDJxZ+W_WHB-eRxQCV|a{7TFJ^#0y>C;{bX$8iy0< zVXxJKByuQCj>^Y~;c<|NL-h`MvpiYVM@rH|KNo|%2Sq5iZUYh84M$z@HewBZ))!xk z!9ochY%H@F!Ume)v1YzS9%|RThomb@IH;()zMAHcjvSG=c4&1%S49n|M>gZ?Akl+&++HkAW01hV;i4wN<8sF+k{#`7S6(oe~QQhTDE= z+V`_Kb%YTS)3%_bs+kVHPnF~)E5)~U*SWj>l@YuAgl=(H{iYDWq3CcQbW@9(hZ`%A z3{a>{6Zl7HByh|eo-BWV#b7*de7=F#WYL$n(*oJ; z^zlli;&wxWC;$&B1#*{m3Pu-|8+?{p4{%pqEy~237u8}5nh5^MI&CAs0*>mD!%sgb zyQ>+V;IUh@-gxg4+-|~AeMyDyzD^GNPJS^V#zG@JIY4xBfXpizAHM}SHIY@Rx>hUL z2X3>O_>r-j)H9kC!E~QQg$u9}QHV&g77xvoUZ%s_K-HkYupHn|R4n9Pu>ogV0!n(~ zjC0(E>fp1K+#qQq#$*|2zIim}H2a8$EM4G_Z@B5tYazwrqS7Mble=1Q(b=?SWr@yj z9mYAfIQ<3xY$R|E(af@|1jY7{8v11gJwuhESe~aYDozA9S8>WV?2fv1XN`^ddjv8c z{s2qtF=PI)`d4thxDb?GLvhV~AP~u^02Gqz&8F;Us?lGmukv7%lGAy^h3EO3h30_L zwDfCoCz}yLye2J|7yiFd2NHbveDpR9(?JMsHgwY^YBqufA^%R{Pz40_Ntfn}Q)w!Z zY2^E&b?M`Lq8Y@XCRqx-%831Ht&NbZ7h$U|dLY6JikK($>faQDBu#KP69pQ^A|rdh zTidJI^yA;8W@tR9njpvd{TSWmk)Dy5b77&;5?Q8Xk5VjAv(8F(OPdDJAFIBx8bC*x ze`=l76z)Z68il0kujW&FHh+;YA#O!B7IATlTuoo9nyc`{2dMYlRQ} z+#`}dRo?_ZL0GxwPJs_%$}S=As@*A1!CMBaYzeL8BC@$_+txHe)BYf*-4 ze^xsUr0YRvJN&K1Wmau^lX?y^Jw-08KG$17M?6rh6M{89d;#Q3L)eQsO-*>xJ^8e- z_9uh{om3TWj_yOMb1H26vDXE%%OPt-X|inT09Rg{kJR7pQ|QXLDHqVVcG~!nzGp%Mo^ z0gkGCsK9NWskq06=aEJsBlweyPd?pCjRQN6SqR4M|;=$A1S~;slYsf%E z`s4YM2ONwa<~kBu|2(sX6kQw*m&=}hf8wBqP5${c?keU=eL`IKt0gS6Azj+*>iP0Kh3|CHwPy?sy^a5o|GIaY`s^Ok83o788TId z&F;RX#r<^e&ikoF>PLS6=dwI4ptZXyVa7W7`OQ#wQ4W#R{JyR6k#}`&UCfFz%s;}~ zUzlFoNlLnZWmPOLCkb<87$5Ix&OGOWihs|4Rf!mQT||YuN=5{?7drQ5O-~b8yi-fW zt7jZpA2D-Uaz=WU|KpM60-NX!>TR`NTTC;_*IYt`ta6{v;HAfZREg0C{`G8@)* zwlWb&5BAe)pf03*ZWdILn7a=8(g+Md${P|0`9`GtwBXb~fY{BOpRZ;Nq>1@|WnBeS z726tygLHRz=Co!4^D~gRDB$~Cn!p-rUIjyaIUljA*JM)-tF!`Rb+OKf$85Gq zxx0asEl%hh#8p(dhWW*A0>mVyk+d#oneu7=NoG+2m=6nvL^u1OUD~e?V+lIhoW8SNHt@Bk`-!wJmxAJd_311lCrMmX zXt$yG;~j)>w6?tv+dRP)UgeP1ObiTd9>%vC(TT|S)g{6HC%$ zU>Zlgq&_ITC&#=%ba?u522z%&U;Z_EAF(RUSH;Wo9k*vyj3DQih^413#1UzOViiWzP4U7Pd32?Hm| z_VV@i3OV;mg=X_%?y>or`3LLxjes(&G(ccq4k~(C(IS)aMAF?%A>Mt&sdhpxnYyMz z%n|eJknk!6_9r^`i522;Xw5jqPsdB;OO^IlzslTmUaW7JpSZQK0zdY$Z+ahiXb3vs zQ63e;77wQA;tP6y;PXsiBWE<)2|S5@NPp5He{oYRp~qnJA|~GAjO(Xxu)?Pp-Y^H4 zy|7wq6yLnB=M?B{&Osp{l5Lf1-fPn*)Ps#c)8K};)KQy@fm<^V1_kF0OOS89BYHKc z8&WS zxZHpAww!}K_I-+Mpx}%8^BJdFak2q1u9cs8&t>q6+7Ekc38}F{QWQ5=P<}{YmsG*M6xVwEa6=)i^WS6K%2(Q zg!aRG)Yk~oYFSGpb!;)*{9cc@N3#}!1EB%PwFws-+GG>hUz4P9sZDG4kcibGPJznnrNlSJ;l@I0b>+x{0~PsbuEcIa zkr)X9+AH~&#Mn9z>8MHU5Df-%o$ah3%ZsZjqpyVqlQBK2pY(}gh#?a%1;>sPdn==* zTBts_n~w5AD{suH(0SS9sAj?oJ>_)?P}=j%J=SU*42v|?VH3uOO(?NJoG~5PN|*IE zSLoR~(Hc?)K`89i61{BIQoSKOx)YP&dY}52_SjhK1W3t7JCkU*h)f?gGM=5tJ-4EM zyCjGhU}lzg)lCz4EuGnCvwJ7h(}2T1eZT${g86;KT%Y9 zYt7>K;Da#iIKPRtf3uWGjS@mr^uIvw&k##mbJD-xKps%7ts@*juj3ddQAJM{DN<;D zM$94pLn#|!T!rF2pu%sJ+W+MNx)UbnmA2Yh>bDX`?O4p9gO%y;yPf>j!$O{6+-~0j zy;dYY=lFddzd9?W4#8R#k;2#@(>KOfPKuu4(KW#Vd?KR>aBcA^xOXL>WikE|aYB`c zvAwC};RBlDad_3=zY9{$DwyCF-e1Amcy#VdwqhAA(sjS@tnXYZ2W^8Oq-PeOb3HsR z&NEZ3fQ_bIs=zD&L<8 za?Sj3?CD@4$SFUzkXr5p1r_~P6gN~A(ikABz1iE#I4XO#71{c1VQV;JumAg}Yv;$8 zm7zn^wio4DY{SO9g7DeQ>#svkc}@8_jT%U{URI&)h)9cjxmr1QbyXDF4@JJLw_qDA zGJA|G99LdSr3=A`+$kr!v}JUQuRw`!^Dvb;OfD~*bwEV5UW7+vPDGI)pT9c+Deh-! z3)+6<`b=bPHl9LM^1hX8Bx=OV4dzx=p1j$U>`J7=)i5n6U#&|-?_<`iKaq%L`&}T$ zz)q{K8PWuHYCf<$Qv*MNG(_}y8XsK6ze$<`}{UfyhNqUQU@j@R{o~vAR?Pwj3$hsW6%dQOLOY z@Cb1Yix_rsrMVu{EQcaL<-*Tbg{d-M(a1kcR@^gqi^xr=0j<-;5rm9Ob@y8}dmRxYtp=Zx!Li1DUJ=o4 zX)5#PZM8bDjzd#AjH7sHdf6^o>pI)vr+iNilPyi&n>sNkr&MG8=8nDlQ~TPqZJ1;hg+VNM^Lz`o->!4TDR9MTHCHtZ--6&%@e z=Tl=O)f;N zub^Y5MFPdr>j~Rl@sh`N*v(r1l^e2o8XI>E870iOZZGY2lE?Hga1VSXE!1zyX>Wj0 zueb)Pd+zW+%E9}Ty9*?*(#MfJiCB(cfNwc7e;DSIHZ(IBY>}k6P2=p!A2$Mjd z+wXl48NRExjdIHzOsB|iTGPHG_c3I1qtMQ-1BEuH_TZ4XJjOkiga|JiPuU3hlcnSCk=k>%PT8HwL|7Vq=&m>P8?)ks-emQw5G}*n$ ztc~g@GVfCqyYs{s2?>())>~g$%7c!&VDUR`>|EjjBE`g{sZ>0dT5xD0E}_tIdnN-K zv;dc1MDyH*0XD}A3B&~?qXU>Tlfu>Cm9IF}vs$!Gv} zb+s%@QEt3_y3rEdAaL$J8*&fc ze)L)Ac!ZTt&USNJ*YVh^Wf!1~;3k--zxRuU5@zjfkp}L&GRYEK(;1q>jS=x~B$&Di z*U7@@T2E&FiNZRzVgHl5;g=p2GB#;gnh^<{Kj0yJ8s%S877j-#pz+D3I&dzps0lfT zj|4k@7ex3(AM+GsA0j@VB&pJOH|`;KOHUpoa3*9@wH;j9j2xf$7{r8zN{<{l6XY$q z+I5K9HGJ+kkXo2JnOHIJMzlaamBWi-21#J|G|PqK}(@jC_1jJi|Z}1miMcZu1OOKI(_Oz4m@Bs8?u9NTUe)#i=p3#}U@+ zy`3J)Z8!aph|8g^ZN*Vv@AzSv5SV5|*8$94qLkaIksDlMbPvkM__p%Bk4~AO?!^aP zE-qc2kb~{4eCYI7PM!SFbDXs{$ItE6^e@M2NeP zle*MiTQ!dA_-GbFkup~`Y%|Ql&;TAqi&TEqC+7*aWg1zn&yJrMEf1$*Fe|6XU2M+u zE{3D=#t^1&syuJAWsgS*ORAu}3~W+RkuixN!nW2GAAoJgLpm*41n~zglC;n~PuvbWH^f61gapg%RPOYWbH((8b9l)zNWt^U zyvI$rDt$;s>)~;=G`l8=S3!yRBsNHbnZYtIsfLiaR6>!5J!MlbXb?$kNCjJ^XjpL- zw!`lkB}#G)$xEpuA_v635)PIblt@$-=`l-OtHBx)kRr7qraB8%_X+OjQXv;ik)k=l zeM;4_Z9n_hG-Nn28XEkDL6AjwW0)1Nh>n0zNes}M@jwGCh_;AtH0m=KumB4o20XMj zt7Kb0+E^_-ye%|aL4yW#0gKEBLV%4;L&NyEr+w9cz7y^jRnF7qs%er(&b0X@YPhjg zod;K42UjIc2f_S%oB4}`v#yo)m9u@|Cg8*af&IvhoIC001D;t)9tL-sM@={l z4ol)826Q=~IL;vQ(2=}G%bnD$B98=>c(fOhyhewI6xH$BvDB}Q9O>xu)t}b^NIENI zeVP72{0AM8c5c{fE)r5bxo@Hmai~^?H&Fw8MI!u;&henjlzoBz5`DSR^8VZ}4y>08 zB?1)&ujJ1WD!k)_U$7fSvg$v1WykD)+KWeJ`xN>(eNCQ^YQrOH7}Zvy+5-Cl-^E)D z-!*!yOD$yTx2(w2?;M2A(UEg|nC1Po<=$`GIOa*WdbrapEb>dtufP@MRu<6@>Aw6Ym$gp+IXECy(R1s(XsAIHI^vTThv_BT?6Ucna6 z42=`Uo80^cHNs0R9GWd3e|fl(?vRv~`J=HDx=_30WPHWot?<4#7pKmvCWmX17li4| zr>xr0YO17vz^b0GGaD+@*A~@2+L*dfVuVt&q|v;X0{KNNY0}e$A-}8LoVq+ywe`tM za5t{fvL>yzQ4Ru~<6LBtEwI+e3HtIWbJnXG6?7UQo8TrcO_&Lv8#Kic+>lh7b)S_7 zI+SOt(n8ZVik~>Mf7<(t0hPgxq|%#JmoZjbmxg;o$EKjzsSxx5+{oumW9?WNoYRO# zZZzUyn#u7|R*AWxHGJQ>CgsS1JU8jc$n&PfHE@Q0$-b21kYF8l!wj)8^$%5FAYT$~ z|8|}D(j+<~j@zZs;bT#5>hA13*I2y|6w=R{XS8ACQuqQ(yU(45u~8~p2K`tm=x{=d zq^ta4D7d+5n_)pB`qO8Wr;Z!-JI-6F7hfvch}&zFt&?Y@K97?+=u%H%WHe}0EugZt za;Q2y=yn>1jN+J!(n7k6WlSxS^L$m%zC8}$lTubyHgYreeUmgn=rl~OrdHIV1ATqW zHe!qXJh65YN=lNkQ)Pn=!w9i!{bX9r@{mF;x4@0k2-&Z;)pLFUPv%fA;Gwh`QG^iUyZf@ydUOeud zQ(U~Bv10&>ry}m$(c$fFb0pI`5`+e2N5nn(>R*^Trx%2@qU*u#YH-AvsyhfPT_9xZ z8UwFbS^;V4uO@d;AjC|1L36$HHS2++CCiSR+C<1pNr%BDa9QD1gquWkX)8I&rh3Ve zCZ|vndy=6O>J8>N|LEAU!0G+ChiUgYcYDZ5pqa7l9*YY$o{OAIBg>z@3uurWJtFRYd!Tn6#?Sa1 zpB$=t#C&ZuXs&xr4AnV;Pq`kH*1N{EV{qQ#r7vKk3&aYftB0(7E>e~%Esf`ur;aBx zGH)MeBCs8&tMM%hHhQ$U>jBj+)b!)_+Ubd~{pR7?N8nb2x)we%lIs5KK*MO(@AZ|w z^2H;1J_+vB>3fblRyotoH-qc@QxAyGg=?9*;p*Jm+w3*vQT7+6!zS^>q!gvBDM8Z) zy4K4tS_#4lp9s}7wC9DtF%(f4$pwlg%P5t`@k=*5F{9T*+llO8GRe@KdNl&G(qxyR ziIRH-s;5eOU+xF-N=EEDs>-oR<{u;LzMCVHG_7x*vVP8;`hl>%Y$(T*KuiNw#d}gn zkx@{$3-e-p+n8xiA$Wyx6kpv=-M7EbYvto+y1>!mx+$aQeh@WtgY)5TXUH3gFDY*# zeO$WSUKvG=6dVS=6UhdkU9EEuKSCb61ZPD?>@=m9R$J#5V!Uig|3x*HFCB$pTuYwa z_))Hc&3p2aJm*J{vD=SIQkd8mBXgDA`x3j1ja{&YuH;$M93LXft^j+g?f1%Y-jpyy zP3VC(8O^w?v5Oq`SZFG_iah^oirC1CQv7sTcY6xKsl*o;EiNZMP_i^D@nF5rcsY!D zPQ1GJz|kD`&*q8b&a8W}9HaZxR(VIs%M*$p$Yd)m!K0+v)3i8krl-*Q(donVD-Va% zS|0D=b!f9=d!LER6@w|!CdbR>1-_#Db0M0$gR$%SJtC}+Htgd7q3A;k2@lY*)w>wJ z_!3ru=MMf-xH^VB(D+nV4)0SE(ZDJzx4H(u{02Y#02aQ;=h?*04vBW_(RH=TEst9_UWv3nz7WvQ3W{)!U8M!n0+glBvPi)-G?5nkK52px}-aWjd{e<|A@8F4Ua-d+_2hA)+9neNtJt+ z>E0Kt)FGRO2ha+H{RI3oe=Q)hpGv{LZ!Lk<puYL(c>mi4O>T{Zvp){%^JuqxERUcR z+Na^*s|fm^ZGvH2MF&bI#C(>;wm0k^ka6&XhwoSGB9GWCiu>|t|IXl&HaCZL2$i#BWq6q2_ zu9|pu^hbLa0u==5el6+31j5I21M5}HwP6%P=*|+_h(Q&oE!Aiy2KTDzS4mrXu1r@^ z?TLvL)rw__17=>yKvo4DjX}zUrTFS#(;&2_IuU2R5v?*^N{EUo-YYqbamG=eZwzxC zc$n^_wqKSMy5AAzH5YKXD4KpWp%3t7&fY}e?0;_0O;c|m`-42f_7ia>V|Dv;%ddr( zt2$K$5Lb*gQ%{y2jjcUN?X|Q($$TfyuOGgCrCS>azsb1)0d-^GhNpw%h}cm(bAHV5 zcS18#1Ozsq>>UG8LQe{qjNpM62e~}B;V+8(@P!_}{7FS&ahO1;9pi5sJaD?Fe^OD{ zH6{YWUySRVex8=@?zWzs?v|dGF1B!fbxv1!?gf;L34#={fTb~UkT({9W6uw0jI)7m zaNw)tKw%#Pyod)3j#GeY2?37)Fz{1kq6rOe+Ou;B8yG~ioVQMiQ` zIE^UZ9amZMK<~5y__wg+5**+JzZBAU07r@d?Ti-qj>6;}0J|#O6&+k~k_R;Y2rz!b z0$|LtfflXdt8~C$T>}sBo}~cYJO&bHAA_ds0rP(G+g^1zh(-Hb7vQgihp;bO;`o0m z0Ra9x%3G0ue^ImlkK+DEGTEZ4G%b65wKp0yOaQpQ>XrlG|N39Hsy@0k_qQ)O~ zg$gLV=K*bW-4-d;ux?M*zaw$~djr1cy#-2*Vgs}4WWdk&c;GuDL3f;Zz5N?332Gm? zUFFuN1Zqa{z<2(K-D&fF;ud%~$_D=TqaOi*TeJ#gQCB!wU4)(=U*W|4QjIk7XblZkEHwr%s7*mg3pZDV5FwrykI{dV_cudDw-A9PjST_L;R zDK+4=G@!8Mt7a?U5Fj9DFp1X=tbn#UsyfB03VnFfl3Hz}RM#(1 zI#3&tb;MDkC^@sa(E;geOz%&q?x!Mo-3nir#_F}j<*&%ENIuKw^ictnfC}2BbmsSq z_2*09r-N(rfBX;*u>6!^djSEUGGiXnL!uB}t%W;G)s$&{s&z6n&_o3WkU)b`+mipe z(48C9k%@_E6y-@@XA}g4c^&2cklescOq33k9jv>wQ5#vxI=+W`ueXPO$dP;?W&b!I`{osy<~#L(A4=+{uS0<7k$!(YC&Jz z#EKlFuFFHf==?K&m(G#g8xUaIfu5>o=F&gb-oEc-{+CGSr*?>Oc+mv@XLdH5Yem{r zdyFCauy43w2?I7c;q%>W7P08cx>&m4t*~C5bkg{hnQ@5R_e1%W!jtE^(<`|9+yYH< zR23!%%zk(9;O0Z0PVue;Rw|{n{6K99Q8NWf-ry^|yZR-Vuzp}bKcFs??LPm7ZTZB8 z`do__hiUEVZD$ei;QmwnwS(DfRXMRvsF$8^8@hq_U4g7 ztJIoISc@^JLDeaxsX{Irj#F`_T8hfBVh=i|oFjA@`^mN+HE_)%zpn=$+g&w{ar_bc#mVrbO-^lSE~O{Bhd0w#42GmvE9e5}-`r!7O! z!{8tndo-$Hk=Ax@#|)$fTVCV}pLqLszB_f{-&@Xw+XXYl5k}qUn%JaPnlO)w!`4LV zZ@pxq*)hG#tJ7EW(}^atQ=A|!QD~gl-)r~ol25m=k&@powjb z$somrttV=@038Zgx5J7U2ei)NjJ`Lec%R^oMB5=z{XK|XF4?u^w1?xzuP!`W^;Tco)(K(nwEoxpnB66A^4LGu*mX(Ern zw%IKv7%EBJlJP@IF-3v7hXulg`r1X0qZUcF1Har%`5P>jNI>>N6&5ialNop+MPd|E zbfw|&1!|Df9ATVO-YiZZt4RHMob`!@@NrrrA{qT+Ei=97B92>h@c!OG36~dCW?&E+^u61gG(GFbP&Ckp!i?JH{e=yZQu@7bVBvJiU23jr==S z_@T?WpQp)cGxO4AFbOPRyi&FDb6@bi7%mot1$nrrKQt_4?U9);XM1@RI(~YEq(!k~ z!ExU(oX)a7aqWKqiGpsou)~K}Ww>AKr<6d`4Y#;I_Qr!l_#wCEhInVk z@G$(qzri@#@eG4j4H)Cw_O1?+1>9~_#es?u>e%L1*vU3RnKQAK{Ed(V@6D!WyD*JV z)#@T62mPTsg~PBGt$^Qy5h{AK*wvd4apR3DF(!a9<;R6=d^3Q5oi~Bc>kGNH#Uyj4N>EgS=>Q_~7pjnUIU{ zI_2>6cv)r>uYs`PM}vm-Iipm=z6nuDp)>madVTCa7U)BdN?$f%yQ9cE{7TFv#wJ3* zxKm&SYY|7f#M|p7ldzpc_+@?i%|jR)qkPR!@GDB~#4kaHKXRZ|EZ|X9cs*}YxNz8S zvCjd7jxc6?ydXR}MXcepPQG_E5g9sHP$<`(2Sh`ij?;W1XSnouJ+Ds0$3GEPC|2cN zzGP6|!ROjYEWwHy7gPPDDi)syL*B>O2tePuC$6}Py&G|PKj5n$q_h{j2vT=#mo( z&{(qMj=>)fN0sh28BeH8J{WV`96?uBsKHx>$ zN0b#%7qtZJ_Xq=C#6J@K0k&H&=?<3s8X ztx;*VB)g<4vMvfs5m%VCQM!_`L>2L3x|01E6SzDU3hbDZrs0@W(>b-U8gBhi5>QKJ zji6~h_Vz2pB#;VMwoUXBH;=r2G)Y^wZ8B-H*oN`YO}RN^E|+b^Orn5D7Oa9M-eF^^ zHA{+7jAI+4Wp9f|28@t_1HbwToz2b}#`( z@Ut=VuS1qfId{t4-=MXUq76Q%#8i~qLf)m8KUv&RS21KpTYiG#{U|uJY=AGL>3Uqx zayni?g6n2o(0pPxj^hTXH|Z7SF`4+~OWftq0*Cm6XCmVp(62|rw%QT_A=Uhscp&^<$Ha;K* zwk8qPUt1&As;PdCuSsweNU2gQq|0~*s6se<&2PD^70ly%N6e!$0`&TtX_rzH@;Gxw z5*0+YAvWwLp+wwe_G1L@keg`+`(XO^+9&c{q-G=dNwPWaD`hJueI9l+xYdJVr9BYh zaK<4zoJ};0*`&o$D^%vs)xzP5x}YuWNu!lcAWHnZ9;>2PFvFQLbE(#mFFNKta+bEM zoOjwWW>fb#t9jb6fP5Fpahrsw?(EftE7GbRPjRanh9f!()pTn~7-KHU_|#cGIu29E zDnk!-i(;_Y-Wv{fvQ7rC9CEq9U+no&PiDYGF>fH>Qy=O3IkE$Rs4Vmwgb{3 zG%a;=C{7I>Hh$Gyh=elQKWb#kg9G4Kl!-i8vc;Q<;>lRf0C&zxl@%de>TRhNLBkHQ zX>Y$LoaLg<02$nN?C?pqsFO)7k-KKS`WoFT zg}b&>>_y8BeP@54{JuGDoB9=rz~OnJFlHUInvN`OztIF`w$eMHf@~;RmeWjM=#3#9 zgJBH4LPU!NkfZG+fvD{y5_6}c)dwQoevn2sT(lmCn(`n~L*^^BPH{+TjH2wYTU^3x zJ`v|9ozL`3L$CB^OXv%x@0E@u^+Ki4!mvUqWnASGNsEcJ1l}`}tlw!Zf!Rq7MEWWf zRGL7+ur>m9I>9-u;XrV4MQZxzBChHr7Vg!##)yF$u%kXJt;s}>8bDKm`0(uVh!+lD zoMsVU01oc^Ga4seX(f!5fy-_{PGLQXd8~k#DHi@G1NJD1b5JC)cq2H8F;CdWiiFl} zquARXBBL;!^q_`fyo;bgW3p!H0NLhBKWCg)S1lyhTwQDRjDQ;NVU{Eue{8G@SO$6A8!GTGcZx1OCDf@+rPIyXP}CN~2Qoo3*vTn^ zXaspVA*nXvGY~vfJ8jvrO`|VWzr7Ql9)>u=tL^blrPGx(1KB`4Tzl)Ylh> zF7pUdPpt`&AoB|Tr;A^MAAwdKRf)y)`+Zw6(5XxQyKJN=jlE4|$GA*__*7Ks^z@X} z6)Q51P52`W50@+N{t+dfR-37+EkUtq5WF;LCAFUyy>&cgqLg|;V9ARS%394XDX^mb z!oe!rh*Y^s6AhtWU8tG0wrV}WYCR!>#YXaS{@a%3OzWm0p!zZr_WDog(FVcTy}>PvLEs zy0;H;7nZ6pqe70g%wjK?t|gmXQup`t#^}Tkpc>{riCRD9Km~MX9X0w&o=X*tY*Pm+ z&(H2dH$Q?Ie!Cjd9u+?{-Lt@rN?QQ{8prXq$2bm#K1)Bsp}me(b;=QW1bCfWZ#Efb zD{|GDJAu@_8`pJdmFX4d;q^jOV-hvMP-K&i5mAy;mjYPE7^@%3Jn@Z}u^@-~$om*~%M7}N7Ri0205;iRcA zX}bwyFq{Wl_0)WoJ4>lI3!ZePW%40XF0NC`O2!rb3>nW=Jwn0X%MGffGEZ{F_`&_< zrHCC*14-Q@vj56-G-XcTwo<47T(E~Se0e%()hn;c^0GtO&3R|>s`eJI;C{K)GDXog zm-RmFyKbAI)E+qxM(rym+3#|R!{+t7Z^~rMT%!a4dPCi8GF{X&BQR6=A=ww)9 z&*%XgtUqOA^>IP6G{Z!xnFK~lbn(5$?Gfnw5Fyt1}|eK)Jipx2+b3-Zl# zSQ#;}T}kb2cl!qFA$`Vd*cUDOuM8Hm&&qjO4S|&jgZ-PU@`z(bSNs+eWKUQc{t($b zZRS>6#LQ4(Z8OLB@d_(7HQl=Bh05}!?K9Oynp)TLGv4XEvRl+rc-!&Z+az)>?{Z0) z4FL(?3^mA_%JNsz3@{6r%w(DhCJVpaqmIXn6nL%vFI?bv{}=q4mR)Xq(j~)A^HclX zeMknJFCYx{+(k1EhW=hXU=}N;?k$Ent37>-7hakn``7S1M>tYGAtBlEFykL}$B26QeK?LlhF#k3 zD5x9szXbqB$*t?$R*&XSo?m`{6RB5>3`I(MVwEzrIs@GI#jzH$JTPLJ9TB9u``Red z=#lD|fG9vU>5c7!!&`97=Lf%kjtHx3XVi18y0Eogzx=FPj#QM7R9&hx)l)r{D$$|` z%C&G&Y2#G&O=Nh9MWQ~%b46+UXtXtaC3|gu4>JIn&3fYpK8@|MCGgK56`AmG!z7x1 zkSyaI_oP))7CaIgMv>i8b`%~>7v5)w9Io1LR_2Qkdu5}L*Yuf=8c+GNHNIkQ{~@2c zM%H{2h)DL&#btB~75OeE*!J4|`%Or^__n6VmkF){HMUo&_nI`%R`GMTIj# zZ2d}FA;G-MqOgkzY(=>9&-^XkfiBO#TlzimpAdMfv6xr}Trlpt$1H5!y2fsUxTR)M zYG_d_GUVOY4GL6_um}!Ej_vyfkfCxcp@@LF1F1{n-TcYej)uJRNh^-~I|o5Ed{$V( z%9Zucsb`a!^(&EW&+Cc$0oH6>~`7o0=mqUZ~jC)?a4B(a8Pw&V`v*}kebpTU(bS4wjzDnJxpgsxh|6)xa&Akm;ZS+THlaCU`oB|Kz}f(TTInJ=UZPE_3T?zj`+p)e>>mAk8_-c{e%iwgdQTB zU3M4{5Mp!?5bDGkZ;V7aP#i!9O&#YumUeQAI?G%+JJ90t#LnSl&4@^2bSQAEl7 zeWt#%E5xZOSiSKkokyuotLo*0cD>cZgN1XlW$)`QudXAfXMlOU-W2TP>N&CHzWcfB zd->mUHWIJXADAzZXdR1nNtF>L$0y-8RwkH`S1o7@+#3al;ikQVP- zM24-hT(oPHdv}`Fpm6|pEAW}xgK(?nS9nsCBsQT!Eu1=CHPG5;BPhl>8PJC@;S4kV|id*Hsma1b7@#o%VDHq@vxyi19)G}AdA&amMX zj&~4_{26UkXJ~jqlo={eL`342B4E@X^MTNHyq7}2oAfgoVuqi{D-w`;@~-BM~jh(JmM z@^!iW7U{qVrlmzT$YmH0JIBXNl(-aJ$jBX^#uk6hnU&ju0A z%zm?{Z3aNcCsh;wTev;3LmDo^ya9Oxt3#j>XTL5i524~@hzMQWu$&{15#8M|%GbC$ zN&VK-$A4>r#!=t+`6d0nM$xnwgA2^f?-dZsk?HI=7rjGN`jIv5&AqO$o5-Y zw(JF`yLu1zr8vsI?1innA1%Es4v~&;>{s~4Yr+Ul%b7OlyB!Yhj()wHOD7Z~c zNE4V!;op-t+Rick5FOONWyc28Z;?KfhyJO2;3AE`#72nU=pW6~9tz4&9*D>jn*|qm znZ>^>=p_VUWGAZVC1Xg4qC7QQ)TJ3N!k@D+jUg`u5o_`Ai2;j$Stc?X<*il*tmQJq z8p#LlkAg6kt*w>^t=W$c44=c5y+)MCVgVJ}f#lMJDBSu3)gmQH!vIOs`oi)#AwgQq zT{Go-eyeDhFxciA>2SWP>!v4h{UVeaN+SOVBbzp+`hWkQ(VmO_r|qK zsj!{pK6RgEZ?&}@{z8g#{gt|!dwfy4OhKBh~>eyCh(L`&-5899Ee_ zNWpNd!t?3n+JVt@%wrM|0yuK@zL!%tG+sg5g}m@X_JH$qIsS?L70BY zsCf@N)lq+xd~=uiY!nkJX}MD~u)X(&hN07}>BW(F~klSkPC{a5lrEd>?nW7-u+0OYJ?4)l?ZnUA0c z=unM-D{Bm7bq^Tg(%V_DR)Psr`!lU>5_w=BOm_d@FoesWy0mSp)s-VOt7o-C)n58~MW5up5wih8=mk zbfksBDaCnH48he50g`58RIZbn{*{1XLz z!@LKCjmGSQ!z0L>nh~T|2g_hmtrO;>$Ptvsf*aAs2V7BDv#jkO9LE&MMjS3zct@1V zOP8Ii2#hhubYlV0DC%o&fp${t{VE_H%XgZ zr1?Sw%|h(ZBxS~21l1M!md154I@eqS1(+3m_f;{fJ>O)ER+20=)2MB+Eo;I6F3T8EvCqJRd&S+w}#3#clf$e>!+7i>Ji$L zZoR1LZ)3MPNuhYF2$1o@0Ej)~I+Z#VHKr#}v2QhMQnX4Udx-D7T8;{%3lt9N!sMu2 zVcg?wA+*PlmDk@=rZNjNh}|1=Zt!cnMYUe~nkaObVs$GploVBxjWC1cb^0D9lr#au zlqVc&zthb+RcuRANNSAD^`Y8SQ+y#M z{>gela1hviG=>5JfkFOHWc`o8`YMA0NEzvkZ48~Av(#S!JX3tXtqaEa$)I9?$kb-! zqM6AQ6YrU&VkkOEns`~Q1oFH*%EZl6vy9ORF79=3B%T{JGzRDr3QE|vL4phxWa7WriqEbWTB1B zDqf@^b1|9*V`-Y2!7y@v(q9gz|8CjO)efhkU%2vYqN{kZM1iP`e+Q`0pU0A8|C_Rx zR+U!~_~+e3r$gn*7ZyGeh^y53X}0~}e9KXeK6-5W3b&$dA4OQ*Q8fb&B`ztw>ZbR9 z0&2=$+9RM;eS`-mw^o=j+6ED#}f8^{h-vbEIerHHPY9GurYi zq&fYk8uyQsIMt`M#Lj{$j_*SAhCuqO@>#6NJaM;*dXsLT6C*wuZ^0sIzY{davZ-*J#Fr&mhEexbM^ zztzLyyzu>BpEV9UjY8zxX2_*B`=Ys|WN6*t+aGI~1aB(cPB$@J$ysnn^_k>aA-ufI zthvX&=n%2g9x}cAKXiEo1$$A!)K#l{V+Z}ijm5--G}vs8Y&HR!c9$0SIspWbJ1%7x z-To(~u1<~9YS8SJT4fhzF$Z-mPP|Q}sNF4dbJ`LC6nLzy!bH`Z!jS7dZydLM3Uoa+XXHY8Z2hP9Q8(6=JUH7@Ziq_1H6K2}}#IpnJngvJs*_rEGCJFa<}1(ni>=H$IlAwlmvvfJYVD9Y1o_hiC@`)0;^`O&gv^E z%n-3XrBOYmr?`IkXf7kkF%<**ukG6NBuswUa!uLICy`4(vLdPinX_QQebNSIn|ED^ zo=FseX-Oa4_A3WdG8qE^4?mA#8S|~bFb82`t$%t+r+uN$$R0I}( znt=x$*>0PT3+W_L`qK2kA(*xxM88+NkeM% zf?@x7SEMhsIdQ~M(Vp1Jm#2kD?K4D`>#Z^JOn7)A9heBxMM<$^r-(Cnpbj~u*z!_s zliqqDAL?w6ap(*P`9NMsPQz=`e9BtI`2ksb65`LW7J32RzdVt}C@H!E7dMYoom`@1OB1c^(>H`(ud=gCxUDAv|f5nubiH71@C-Ux$2Tck0f)LnI!zd0%r|ww>N%y%U$61wQN`LUNpC3~x}$1qweRYW9oQ`O(2Fo0xW64&$G zzsAD^kt$>JH%9DVf8;JBiKv@vO<=`5G+Om5XZnX`dls#1Vy5`WI4viqq#B=u9G{3< zHkq;>nflf*@h`zi_Zf;MgB*>}PvY=(5e7R_Q6fp00;bZ`QR@Q9wWJ(0A~b zF)Y_Md2I(JPRf+lGZWbrq7oPtzi7_~wc&nxNO}9e3-BxQVA9q35_VUUDG2n>~ylJP9m5lD>^mnrYdbZt>toyB2@*HUlG=eS{vn6 zYqAy1OXWGupBSGJ#ozZ^6DA4pV0R?XUGAyQ(|7#iUH2Q9P)I*#@xDf6*F9TVND8s3 zCMhk&%z=W@c(W*<7*}PYV``o$v5zxjJ16JtsOZ$8{UaD2#SBTi>EkEy&{uUBEyjXur#r#Y zNsSVNt+k?21F_#8$zbRNNm5nim1Jq8OS-1Dg|qk}*wsl=-qdnFd&lLBOr!fHA~H%PA)rw6@cN)p3FyID zliMGrQ!e1Sf{t*e{^$cWrkZbq&?jC_m3FdehFfM{tswTxvNX~CRmnaeJn7|96(U$C zFi--qY(4wOhl1-;OdBL6Gs)4sPWCtS)n<2THMW=QFSFltW0bv+=P-fIKeYB0C!t09 zBH`!?pokCiQ5l07eE*i+v`PvR^8?MXkQw`TUGz96IEL{^=VGtztW9YNnS4ccvYE_) zpfS$?3m0X+dINVdfV7~QJ_NIsKZG&ryVp1IfRccJ)~VliUZ(c>Ylu{ z(7)86v>wxlXtW1T+RAvX`Y#>9U0msc6hm)Td4;rmsk%1+(?_2|ViGnZUFz#0$T!)hJ3BYa2@ zP}b>EpnlG%&oX1TI(LO6LIfOBT0;y49=d`mgYHAV38{O}5q1V1(POu+&ke%rha9fc zKA~o7E*8Hx4-MGe!-X*U$oTIxN{!SbKUBO%wPLU+#^FZ}6!2{hy#4NK(0#^k-^O!< zplcQ6vNtPzkgm8n{I!T>fnY7hQ;xKFyMr!l5>jN`t~d|Fft_Ex=moH#g$@4bbI9*q z_$8OpW9?JEEfjpEUtsM=gEIsVklGdgvastSMnSL)F_f!?`q?E=(uEz*A!}Mu@H4z( zeBVD;G<-dM2tMl<$s0&eja1v_UQ+TTdXu3Ic65ty)2Z@?8ngyBjQ^Cwc>y&Ftfk>g zY6N<`MPCKl7vckMm@NPu6rc2~wJP@pZv-ox)uNtby#~q^CVListWSgtgFO*KV<>fe z8FDqBYlqv+SgZ!B6x}Ow^e2)%lE6n9wl4W59wM)eNQV*zV^eg|VVEQ<6R{xdk;EX# zZ7gZLs^urjagd5Yg0CJ=lTihPiMw5Ob$MIm|I+bA7%;Nmk zl0m0!DwjA~#YEn%;+jaxA`VT*=_qu%D4(#jVLZVkw z4;3L_Gt2qiT@(1#LCa_8T+$(%u+WE^qK3hqQMVq@osp(aKCj}Hk*#=&@1C~wk7B@$sj4HCbWUl3uDcKFV{_0uv3sk@Aj@75C zZ+Ue1k@`E%Ug1^T2Yl{!HaLS%JM2>BRjeC^xKJ9p#SYNX)QqqaJtVxJyt#asWf6yf z7#VB1siNK~Q%Ko96b4d+-n%*x7GRt-_g2fkG&kMpz-bM8O$OQ2M?`k#N>a#5p(cNwn`?;-fI zBC2eSBbB?*Y!=@Mcgi2ySp=_7SW)jVgV(ap?M)5{M?%iO$d4f%hh~CIMmY;2({~r?#yzMCVH53YJMsE(hn^D>O0iCCsG@+8n}ebNq>jF+aG-LMBIc`6WAaf zCYP5tO~J&JqBd~H)9SC7H^>T}T8HK@n#sU_*-vWQM;{}vuvpWOieC&s7KA8${{fPx zbeKNIaMLt$oiF779XVay_hBglQpFu33Dg`28nh@!1 z!sZ7V#SKy%qFkG9+{sXA;0hv?UtRr#cel$vyuSj+fCGNR%6{q>6~Dx7rPt{XfDLvk ziY!Lz`ktHm9}V;i+&8Ob29ayp*tKNgd*+VuoWXe&jzVsF%%RUv@NupW^HOZ&<1d94`?@ zAGwm2pr`N5tK>`gG6i^PRMM9aHa@b=zKhPM=I(2Joykze2I&lRw!R+aQ{->-GnJmM&T_ zGtzm7PaS}8*X3HBd@LNwj?Na1v22=(B=}JJYsi*v_Gr$p8Xdvi@c`)X{%#J#O~ku>l!t-7U5J6UW8 z)epGAi#x^NIy~gU>`hsl{bKKy?f^^{f<5BgiPO&5!EDTDpp#!ak{u-|JFW_() zgw5QqE9xdIMrbDGbA9o@$NF-~7Fq+~F=5S0!T%N%lh32C0?GLJvTP|I@FzWJt zNbsF%*G6sgk{Gl{x7V#Y#GVX?oM*RsS7gLhYQHqID3j97@Gw6IB^@gVC>^!zMweKN z{q!YqHEbZm+a;j#0n)RaFW$LhlMP`(!vgneE6xb;rHp51M!4VD*QGoVr^VPF+${C7 zk&EK_Ua|^Ey^tVZwY6K8qP>Nyr!;OK%*!86`B@>! zdN|S)fuW}?!FRW8fz<;N@uG><`PVnaD1UU+1KMZ8Jtvik%Doluas zn$Xyh0&PD!Q|3gd!H*kc_|&yJie7Z2)aO}uMg${IwAv9>Hdtb-L;Y+uv_<#}v*K)s z4?5%R`YJ71!u_JyDK?`P-6}gFtQ|g@4tC*Yj)z8y0M7mA#FFk*au)RGnE}Xku=f+i zhuVt1c1_%!f>1h4A-S!^XFExD*|I-L%9&mx+IcG&txmcG z$9dcqOBQGM9L~DV3>)$kswUp`9hMoNY&b`XVv}dZiR>O|ry1Rbp^@&7T|0{HRQd}> z%!~B_fLOuikLKy3_(trR6);pQmgEde^4DBS{w$#?1@S*}CHEExwu4c>x`kZ$L`&g( zF%=h74B>txEw%_tuDU=@mT;d?9H8VWTXiK}1tsj@Xt-i-A{<5)+BQaBf%0>r6?oV6 zA>s(WQEfss(GOO4+#U@$Q+-DHAu?|waTOh$0R1c_LhI;b$|s<~Pqjkc;l)0J1-JP# zDttoBXyqSKAxO2Ofe#8`#{a+=1@9@6Pr1H-oFBh{8;)&i`KaZ$>q813lJ<+M~~<_OSS8&r+B)Z(tNY+2X5U z1YoFD7uucqJ3SSsv!YY*Ld}p^jTBdsu;}ImDno{?NFz~*_`q%oTRO<98lWYIC)(VYX%!LOrnZRwOp4#cq`RXG1d9N zux$wT8!Xg?Q4$O!Vc%@Gd1QlaYeN1j1443iEWHv@eW`iD%J4Mm!Vq_53u`1L^@U?I zW~H|V66+^ghGk+qwxjGn?2% zPmwo%I0D&?2B118a`X3fzET-uL3Fxl3>Xtqnlopde+c5Oh*#fc3jg>h<+z?`1VDmr-c_AkXzcw%JDLcq1?S0bdWp`3!Dmx`!T0ff7fCo8Q z7Qkt^cs4{(UblAyJ0Oeo@Q~G*52UKGJu2BI`sBudG^x4>*$tE$pittB=$f#jXS~k~1ZfeNx zE#nt_tlipz?D3evlv(G6e^A?>*~0}3zM3LenA|LBPmAjSs;iK_E5WgLOn~_ce8f!| zVz1XpBnUy_0Anq1q!Cl`kf`z+qR7so0?Oe6qUjTQ1Ii#K@b`Lu?h~|wGxXJWn&p5S zh!Z&8z2+O4O9#a0IVUqqjvm@Bq4?~*|o`5m9+QCSN z`qa44>=MqI>{NRopJJJ z)_Go;kw+79*ic?yO#vHvJ6BnTCMh$!1_S)KN{4KdU=Y1#reCOyc$AHacOtDQuh7Ds zb`d=cdZ$Hh9E-2A;6q-NYr>34)C3(a*aYTCgM+=zm-)LX6}I=3u~%mua%`7za;dLJ zj=b$qLUuwK(E%Nl*hljSxzZ5s*ySzbO0YH{E6^#9!mI_kumDmLW7by4-BzA5(J7M` zQqmSw6;fO~|BoW1xMV&Nu{Y=kJ~7(w9}9dTdwhbA_ejdC*14&tE^ME{U$D`(LWVa4 zp9mO)!JSWhpZMIu=2WKo;1Oz&9gr>%59<5l8OI^Yej?uxmIG)wR5|mM!F+0^kI>09 zXcq;mg@wC1V!%w*A8eB+z(;IV)3>&rgcX9Y>PUf*_86-XMVpjalw{?F;*%zx%1$h& zhZShVH&qvQq#CO#hIq=f5Roj?v~j&Udx!415Gq|;%DJu7`P#PlM!Nk{R`LE88;m@V z&M6Uq$)}P%Fuvj~Ccircav4Yeqe=NgkRwO4-xzlZP6y6xrg5TM z4ra^641@TgJ%&<-exqYYx*;Dq+G>d(v?ZEtU^|#Hm}&0W^zEiH z=O$n(9oRaUsREhj`68GoBSS}h)D+94Vn&3Jo4+=D5>Lek8g{!o!4T~2uzxm#f`Ax+ zgMe`SPu$qkOAaV$OXCWneNCA)RGg~qmv^m7=kpCb){DL^DM3dlKsV3q32&2+#>wco z_nQ>F)S$r&5x#-H6-Z6X2r;Tb`=&7;KV@BK_J6#6?o<5nwV5ag!zA<2VBV58)_e8X zFA%y}w~7PQefxw8D5gX!>t7_u?mi1$N?CfxJFIG7Q-Ip75f_Rpi&;4npFGij46Yxd z2b*sOzos+77ozU@N>vUCVIJ2mo-F51EzW~>2uy4xHEc>%2#}^TlmJwC(xB){vINw; zU1^ZD7nKrBgLg>u51oQq~6ThfI6)wSjdu%4(>?D+D zrly(BilF+1P4Jx#CRE_xH3JPcW=b-v=8@tcupFz1og*OZeKTo+zG$ zF=F8erc`k$zEld7N%g|3x)y~B;Ga|WM%?aZw5!!J>quVL-6ii=obH~_ll{lyVg z&@sEHKYf(GBKOmO^P%^a+@?dj_^1_{tNO?tO^Z9A=*R6gNBsAjK{$j-61FRC=%bnR zkGNlbaAsNLtv$j%=vMaUKlC9uLm%#d>z$5(ZzHU2xczsh7g2NuDh@7Pjd|cc(QLGC zax;@~8uq40P-B!DFK*o-heL!&f{E1}`hW=n$>`>Cie#KOaDLg>tp z*?vakL~x!d3l278KTsML3>65bU0f@X9Z#dOuf%!!FT-K~p+CZK+Dv5)Fz-}mnr!mx z);d!mQM-;WMT+*z=`LkGGI})$%4Q0P@4x3kRPmZ~yzkec*qfX)+84JhPw1>JiMqSo z*eXJ8p*V!EuIbUh;$&Dtm;UN3PmRLX1;d`2tE6aN3kKV)?MkKw9DqY<^@;p|)ferC zXZjDDIL{`VV}{crSE;Bxip^z^qTStQgaVa0=b^%MW~rC}KKU|}%4FO5RVmY_FWJwX zvlNoWRTozse<8w-CylH%9p(r>A0aZ#0OxcTr$2{c z(uOWcEXF750hs-M+W_jggHojPsj$$mUERj}ru?nN;@khl)jLLK8g$#D-LY-kwrwXJ z+fF)m@`i70+qRu_Y}*~%?C@sqd(OW1+haUGYdpVJ)m$~#oU=$KgoY5O#jq@7Xc z0UrKmm?T8pM}7Z9*7R9T6Nh?ht0WGBfy#Vky8~Rcd!aZKHx0m%+hAaeq@vB>3xk?nd-Qax$^JevQ`=M0!>PGng$K2@!O0`YQMov2avbSvMi$0 z9gN}0?TY4vYn7FK6EI|;Md-(Rphw^M6>Tc7GlYxdMkZYNf;*u`v+onNgvlyf-{3kx zvq`cO)4|$Uxf0E8v9sJ|u=m_M@HR1U+ZP1xbs@Bm>uyuSx?MMmNE7)*#;ByO-gm>> z@#GgSjp_{3DUc;Fn~000eRqYlkv1}C;DI-c<97a$-HY764d4{oz{LTl{8FU7TNhjR zy;~kVoZQVJT%YKlN9uCJ2t$++g-wps+RAS?d_QYrf-&=LQsTS3bQxNJXHB$RTsh~3 zJ$KtpVG~-JQx~`+%Vp=Vs0|;3*gOTumUne*h{ujBL^~EAzo{AW=`G(EgFbaN;Ny2S z^g6Z5#MJMC18y7i3@fs#MZ@TJ(Rvf6?;@+Pw>*9v=lu=RWjBgDN4(Uc{AYq%gm*;X zO)?VN<|Swm;>@HRa+gu*6<`v~Ive`qYDkjGDhEX%f_d85aFg?fiCvtN1OjD@*Rn!~ zTSWV>yP7|n&g``|&z03%iWrKvh%rcF&(s%+^q~)LJfJGCJwk|rSykMDf;p>-#6_SE z)K%*fMq{oaXw(V4TGtA_Nj%o!1i_&!uR9{)3Yk`qiPB=nFzl!bT5mT zzRcj|hjNTsNEU7)4M2@L0|VBD8?7|U5}an(v@#Ff)T!UVF|c6D^SLH!A7iDU*1f!D znOIT)u*M~^0*Nl0c9ms_t?$h4f|L(v{&*4z1EIT)gD~o zR2{C}%pvO!PpHi+zT{W#s7v1Yn>1p#utppKP4mYH6rH)FrQ!7N0zzM+CqrgFQ7_d| zGk8ayPi%+abRFAKi>tAQV`g7ihe%0k$z1YxMQ>HL_eDwi7A#&JfdQdj1`%L9=f{@=CC)f!$IDqIxyKf^u(uhU=!}`9A zY%Z7&2)Y&GZV?O&3AB`&9J(kt%1#`8)}d5;LT4p~AB{X2Mb8cBOMVoqJ8Y6!W*P-+ zBkO(c$K}=I%#K0t&peO`o}xeVe~mzn5)6gJgCwCngVp`KH?w|_X@w! zZwPywW(K{ibViXcpgN0YqhLFgL$^UzF$Uo z#?y{8rQ>q(fjHFOu+f%}C2X=ij~r1{u$@_tevfQ<1B_X@@hQ-SW!kUzy%r~0$e8`R zurjd6VbHrGUe02p;nDuI-8{4z|5tG&a%x>`?c$ATCaKb{W(9yVvF9N>UAzPqvgf4{8M~ik2YcsOq)HH)`g1cd2(>Td!8_x#fJR zx_c$_H=q*2)G)0tO{8P@_2=(qtfFa_hva_{rbes&eCZ(R#8S9%h19>k{;3g-43XM$ z#9Vy*ptz|`=>O8dd$lBy@D0Xzt-9gfz3;~q$pw)(mgEhr)SF~|;GD|+Gim!pJveFm zj@HDa5bSv8O+_fK6a2HuGt8)HKMu}3k_jj%lm~D?(hbEu!Io$pq`>g1fKL+?`f?MX zV*tb43vj-*!@}G{zql&2cYZ~CfJNhz*A(U3Ek!qX?3t5x(l@ zN0*X=pe`J~_$h)YimON?%!X|$0qtY}Uob}GTvq<@V+lVmTEBRaUwPHQBZa%6^J#VsZ0VQ@SiNG z*5+UTM`rMURR)spWr*nCCJVf8r2*A{wT1~dkcp-XNPuSm>M{0L4*kD_eN7e!TR7xl z|2SJXFeuuh)wI23(PrB);%aVLi#MTV>QdCdXc=?!E=9C<8F5!Gv*~FVwm6*msOv7* z-ES5L3s0WgyhVvzR3F0EUOCTi7sveFch{H(5Ov^R3AbTUlA<1R!sy#H`*tvaT%|(& z8~+X*u>sdmyV)$;#ed-yl0^ zkOBNjFkIvo>D*fl@cfKM<%M2-94wdNd)(!{d4sNhM&mwV@e~GZkNF)JizYA9m>G;j zW38fFV|BE73R`m#l@G>xRQf-B3Rt7AyZ<>@eO%hMBcw7@SY}M%AQJ?ODP|(0- z=QcGjhU?QGZ&$9Fn8JJ420x-}zjoRW5JRKrRX&r6ubd|3IP)XbQNlU-Ok}6Gv00pQ zPt8B$ddgJIfds*60fWWo;A8x&>{}7xU7UsP%==`LMbrwY#KG@ajz+~~SLQ+H@c<1h zF2p9*r@@r;A`&SmS}PQhZgF#4Yr1`IG42yDz^GKyF1ahh6}wumBHZjGaD5TJ*DurX zDpJ?1Mj0HZrH5YZEwYWaTPTh&mdjjPI>)3zNlbWB(DJRQ zR7PWEh@bT1{Tk>naRY9%S!9{V@qo8YLnXVa$nC042ti-9R^!rFHi@-e=WB)d`PVe{ z(ajTG-fO7SFhi>>RPIL`H3s`J5OW!wMsH^4BqCpq5=|* z1}NyMuTHm7nBVm>Vd^)$8yxPP^@~@kaC@0#>$M%}PxJ&pRUh1){9(NYPe5K=bF_4~ zrZtMTUN#B&%_tT%s#Y&YuRsEaRVMpom|sSP1!=N8bR{5(H#y>4{783+!=B4qMSxyA zaIS{;$3_iLtQ98Ol|QhMre^<*jO>zn34y-0^5v(#a{P!ix}d4F86Nahj?yjZ(F-%` zdH3K!umq!W15^1PCBm>3IzZ5j*(uq7F zS$PK$^a!eig<@mTvVo9EuEPMt2)v`4=mwp!24lh}GGB-Vk}LjffH<2yiOurt*U*%v$X7b<38ER; z235&MxD(=#FXYvTf}AlX!H|7NZz|H$U%sm$ShTNT2P6L{Sx2bQ5ZThxVJ0H=3n}R; zF3}1=uxx6od|#q6`9iOHMxo1iEnoC^PsCJdX-|ASUJ0 zA>PRX;&S0uMQVVAB|Er{@Ev+i?hZ9ZY}n}$W{-i-pEE(fN*-#y(lTZ2igS)ZsFZZj zx2kLmbPtXMZ1<)F+qMUR9Ald;l0Nj<;kgc=X`emRGCp}mj{d4736sQP(_9&tspU$L z4g)x8W67l;(P?l(*a#g1eSR3$v8W63<7E^&-EWr%Yf3R)!aS@gSUgazE>@x=k~T_E zQ*IAX7g&2?G z$BdLx5K@SXW!02xpA6H<))~@;N3~Otf+mIiWh#fo%_rrKuChTA3Lb$FhLSDNqYL`f zwuTciRQv3B1#p;FfIk4)GGoFR=p%@ekESZA=-`_to+qffs$6LH+gJ{ ziPkKJEf>=0sgXzQ0M8B|aJp;*)uK?#7rU;Rh2o`6L+;3G6u^Wgr|j+#=Hm#YEd<_!(~sQ(+*kIh<}t@0d;R#VX8aHQAaW zM%u}F!qKq%W92itMSnMSgrC5k=4}4pjAWNS@N4%A z*3+1(57ecrC|bHcGdZBbi(t*evm}Vm7zapUox%I|CCJmZ8d(9SnTKZ&W@D(o4O@>5 zterHy@u=WhGn5!~zZULAld~AyXK3rjAZu-p#P?`!PA0Hh1h~~Ov}*==Pd9jZNQ4>+ zs-{M9pGyCF^w+sDsQo3d8LvT`*(lOfF_vZ(t7sn~qQ}ZCDTuKt@X@Am@e->EgaYh~ zAQ7`U^1&P9q2eV9%k5%|X6jgDLFnOo=GUGMr}&BSHxW?6?9tRfkC>Om>A}kpg6=qF z<#mpOIKzZ#SH4qiW}wT)Q;)Q?vSw9zA#1bXro3j$2?2&wv|-7nLZoPpS>!ttW;e^8D7wKPq$zRff+w zb$%Oenr$c;{(KS80%y3!dn#MqQaEOefa&SL^XsLoFsV7 z!~ttsPF#{I0RxwCbwO~8FjP7m`sNYWnR_QB4(7jl zwZol*o-zfX-ND616**N-LOnu?nZ)jXTp|*0|E7+5H+}z#%?S7?|@Q1nMhJTDQs8y6}B3n(NB~iFE=&w2#x$`umQPnQ5>`3b| zWR3x)u|)Pt3eTnH>WFhq#dh1(rD9(|E;w)zUy|!n4;WwX@qEi7>NHk~!dD7MyYVQm zBe0*zprw%11>-)U%OisrEe)8kVlut%ez5y@5Pj_-Qa&NF>NIv34V15NWpW}jj|;|& zxhk!?cm4ER(0^=y$dmwn*3Z*^rsyzWvfC`B#+1=V{bnL-t13TO$H4aDLly>{q?w)A zj8By{o&18w#UI5t9>Sa(RzJQD`DejbzZWjJWcoR7SpUoJ_O>A2Mb|`ApdWw4#3E2& z)~#eoNRQJei5_maqLrTZNmTN2NGNkAse&mIuEDx3N1PK5pA+lIZYr*Be=z($cgCpc&e+5{kSrUHQ zbl5qb-XAWV1>qaqvADNhit78bz&z-doWd7N3O%Ap>&>d>#utY+NfueLS;)0OPSN=Z z8>gzmce6c_2=nF^Mph3P;*Q4K<(hYH)_F}GD zQ(D~9D4O)G$X8#*n4b(UvThocNX*g*F+lKq9+MnWOdsN}+XBU|5oeKW=AwoJA1NuK z#X?}gfp*g`&IFO`pv-0)7P#XPyWXNfLY=r`LVZolNs+J};ktO% zbR!eo;#5Jkw%cyJ-J*QV3>L&zJ8mS0-CZ+xI-tz2wxqH`OB&N|f{C_WVIqn15n*Sr zuT~qKST9uY)y)-Bk)$2fJt!pvbi$=J;296GMOw{rh>Ipu7Z8OMrD?O#x+FP0a!AEu z+nd~VC(vJ&=-orfy2ngQ;0#x!@uajwhvL z@6a2D8OW9hlPFS`jzYZCm8jigC5u8pkUeI@wufDnq8hwBx1=(4^vB%sYRmhkSj_Ni{(51$|A}|3z+p z$EA;4d_^N7j}03l=2@CfD4=}Vcf(L^KfkV6h@$uoV!#)_8Sq7^{dPmZuNcA45i8K* zPt@uE3>f2(^9~-N`Uhk!w3g)nB0BaQJ~D#MN*4COmM2Ly;6GH40D#xnuZc5#zAyLz zRcs_50a`0Qdy>KK#HlDvaKq5Gd|N|8)IKV&@TD@Js<+r8yjVW%kq**b@i_7N#5xCnHaf=a?~TS*ToBB2OUB)=7%I0o+IU z;6t`QF|!z5=58IK31{0xtPzx3eNyO{aYo4J2`&+$ItI9-Z1WA~hr7(sE zb4hTSyj;d&Y*FxYKK|KXx711daKO;lpGd~E7ek*XLhRf9=_`mJahpBSJc+;@)B(bURd*i6uRe7GxK4qk>|9 z&p)5pokTCm3(qX-*1(t>w-EKCEQ-cCT6B~nT#_Vt!6d&j5?8W~cy+&8Y0zj)#bXsb|o}TK>=5zrQ=eW z*w(G)5qM}0V|_TfkmnB2#XIGAa>nBjZ?7kSuQlh3aH9T2@d&8M!YvZHl50}{rRCGR zknBP(lW$)pGo$G{oV+HM_>BGPdx#@Cz*$Rkm{Ne-$B7$dME8=v%Dt;z>45!r!UK4! z=QY_6xxC5vs1U1qbC(noPqRm`^vm|v(JA~)->0<3^t5tYqz80Q9`S&lzI;Mv8~SoN zttopPR>xA7n!D*eY&_io*Q0b>c?zDxy?K)>0O{qI|1}FcyWOs{!d?4jeWJ--!K;O*iS)dZ-Ls)>cmAeq{UZP)$=V9s21O-LEw;Hj6i|5l@Su3ITefpO zd10TRw>n7paX9_#cm3?zJJb2Lv;z3R^;eJ!ods)-O8FoTMovURB>n-2W{$m0_-hu1 znVkwM2T&4W2{VG0fNJfB6CQ>VjfFHy9smxAl_TLWjc+hRhl*&1PzHI>1Y_{w_p^GW zDCWQ#ar%u13&QRlM|t+(A^yee>LS_|7x*M6{Hnm~9ll4=H(pL9?;_b%`?-ea=(2F) zPPZi`<&n+AYhh%$VS@$8SV~m2(`f`>CoM^~RMfQQD{mf2@bZr3=BvWF4YRlGRGnC^ z>R5aK9{YIVfZ4YrRE~%)9@f*bAVyY_2t>wf%GgS}vVD^;trjAJq+shX8$6LY^7v|r z)IDb62mU-2Ev0z;YXoz4q0{59kHPso)RAB-Q@q<3mx&eemd}9et)aav;;owVw$CYk z*fg(3`xAxKKdI3nW0=?>{W**mCqvwgRzgIxCc|So6KP}_INP;aol76m{i+g^X&HD* z^x4k>EPu99%C?QtOn??kS(f%RwnBdDcXp#}9o1sinyh#M-nh;KOHHe)&=uI8$?bb! zDM&^ahPga@JN5wT5s~JsGLEY_Y7qSB$mMpneC`cZUhl-c;S$KL3FKob6%)qfHfp(K zLmttL<^@K6&p~(#ugpY4?zyK%k^W4S?Sz|_KVLnFT3Tsd-I?v;`}kc|$Hj@M@LjeC zha3!F;9>b~51G`oC3Z{PpG(|qc3JE!9XFuZnU08}y~qH~_)EI2lwyLtr+&#$v(0dM zmW(-uLeO(F96nrA+d+JmS0r@Ho)-Dj;I;1_@EvaTFJUXisqQUL)4bAePAbP=jpzd| zXp;P8)D`(fsNK=)#vF6*SAuy%qYXQI_#D4QhLQ2mS2yjb)^Ea`sRl}-%3D~B(+jV^+HR;~jJGKbb#Cc2R#8D`AhN4JQ4;->C-xU|bmLYL1!cXM$|>RD+N#wd7o3 zt8_GV3RAMH8}ua`RY#gEWiV^31AzT@v)9CnSyuGLnuwK)m7Is^Jl>@Dun`c-IYuhU zzm4l}ip4fDe;Cu5&_@^OEuaAS*nM{8;GC=!hAzx4m2wWu?& z>6$MbS9M3fAC`>!RL z7#9y7d~bi^q%VC_(s9-boipfjNxKb9fBAR0%s<~^+C2!OjX zV@#n|)}L;%Mr3k2LjF~dHlz)`0})%#df58QpP0tyvZEcDaaO!AAh|t=eF=QB>tz~A2VZY)A ztr|Xkt57Xw$pwUJUuL_7n@jnfg8)=5`Kh)W3JyQSZB~%FK#_OWeS=XSswsW@s8!|j zfb27Q+J+#q48}`Do&SK&&e59VF-U~SOWag@CK~k@(0Ay+-K|1Iq`XF7)_G1R#Dont z*5qtuuoWX30t0)9`eqc|d}e@fff*Ee}WI#_q!S5SWmipG!4Z^f0^ zgf$3@t$Q40ej#Cv^E4;gBRE3S4w{XRC{kDC?keAM4-aBKsD43G45o5Xe1^#G?YxNi zga9IFYkK<+5?iTZ-IcQ<9RcBd?!CF?8a{+>yK3)PAAT5BC6gTy_$Y1$;_1PVpRwze zae9ACU?{ftLnjLAr10V#oMmm~^GZx{_TIbVx(_qzrV1y>vZHd9{=s14Jitl~2lZ&N zJiUUG?Gv~9V|ii4wjF+!RT>el>!v2D#77sR6K_iFY=FK)j&u2mq0xg@m3_BbO#qO0 z!YM9&*x(-U|3pr*!JdNR@0RTW;{Sig<37LzWGCAxE-0ame7WOpEu&-8gvH8Mf(teuRY!>~DlNeqr7SQ13PL@Fr z@T-Qd3OWP_fS@9yb#`bU&aN$RkA{ zTJ9w35PCcJ8%L&%Sw&3dVcLP*a=OMpGW2gE<&h%@=UK{`svcq{=qaNwwm^`KTt&N(%bvYs$U%E4NJ4FQZ(Pu+lU$zoxOWd=p3!)gnYg}5>V@WqG& z|9z%}8NHHyn5FT1f?`v6wFViTVGTgzWY=wefX{ze{a!19`8A&7q2tnvUR^@X2b5#9 zFg>|UE_%k{m$t?svkEJNo*QGbQk06E1<=eqA&p`Bk#vY!2TuwgDc^1O|L{i4md?s= zocn`kAsxs_O;@JQVOV&PwH7$O7-W^9(L1gq2erWyF?;%*$a^S`?i zYW9H!b4l0f#Tfz6gO*(6Sj>;$v_@cOZ)*MM^OR^r*)Nd)S<$LsvH}&~6+QS}(f?mB zxWi6PROGnVMwY~(J5F9iEx#qZE=1k!K#eYro=*fWPV*agB$14R9x&L=g)&+`%S7Y8 zqUse@K5C*H5(5pMNP{LvOH~$TqAsl5=L!toWy{>GNv7K{9ZkVgW?TfXWuFY3tAkN& zcbHl~Bb-DLUG%nUZ%-#ULC}56i#su!XzAjGL%i?1G5mK6BWk)-uG}Dfx@yT@S>iEV z34aHdgcrm~qpLap1jt5CXApfIYq8*d8b`qF(O%mp7;1Li;25$F>a3A&3;9Fm+?{@+ z_e=h>#X5n!%NK4ysplc0_b3FS^*p43lCHCd?K6vbQe2N>6TK*f>j`K=h(s1c=G}{_ z=P)d}a8Vjv|Csjs4P9kIK^E&MgFM=0<;x)!s-{qRTwOcb02;T8-JEJ{nHUoCXNn~V=aC=|eL%~TvOMmBk@JahehgqY$OJUoy-h}%%Brg7z66ej ziuOBS2Zh{Q=wku>i?qF(#Zc#c77LW#dnc%eh+4TJ6SMVI2oDRCfcDR|2NIH z!w!*n#w7{UTq;VZ8&D2y*&qX1vvPxyl2 zXYtDKf46+Udd2!bm!bb!CUgXm_`#0^I2?CO(gqV#MviQfoKPOjCBm_hi-Mw{g80&@ zNp6!L9$I0Nu0i#oc6h&n!NgWz5k%}=jJ;V7nI8$ zY>Huv5TP$-D%{7RgKy+vLkppTWlrt4+vTm@tpR$&K@%)vHB4;0leY3*tyDDwxLiKg zK|~d2!?ymEP8FPY-l7bs_H5N|sc2d#(F!jaVQISgT9}pgoCg1XDLD?43z+J5CFl_O zjlJYC5sek4mR<)fdIr1W-XAeiIGX>=rrvg@nMSyK`lCYXHX}41^+;j( z*U!@oR6*xL;D})D4bNeF8lwvhpb0>K^c1SmMSN=6HWL>SbW{(7gkzjhb$9nOTf;qE zs6sL$KEiUc2sb&|Z@CmxuHh4u-A#Vy?wqT4@TFgcwmWX81u|^{nMg(8bcKe6FoHz* z*qHp`m>HAd=nUhH4gi~_yfqrGBA~H#rhj>cv9P!e`qF?SaK+BI=A-X`0fVhgw~Lpg z(@~oOZ^YA@WAV2~sv{%3Zs&b^U_L@3eOD>%3@-dgEy|Vxf?bLF)Z+ZDy%>|i45PfF zM!uU0qg5(8eF;0YT~J=6%sPY>v^M0VDB0wxZ<)Cxp{*hiVT=jg@WCrBP(MW|qa2Ik z&4U$=v<+@FTWa7yflLKpskmTS9A1P#m$8#)o(OsJFR-3)mIEOk#hP&qn;vqu*ZAQi z?|QM1VTh8flptV;ZEV1Duf;>RxEI3gu3CbSg5pX%(qFvNK`sN5$t||hh6I~3EZ97N*K2My;DUpG*JHQ#{Z5%WKfbqis~hNQ$^pZKP2id4<-_!44Ckq-({;hId&Ki^lX=3UaZT@AB@v&)#Lq^+T4ZcK{W4O z>cEMzZ#3t$!~mY?zS>uvsaSRIar)QLd+7JM%7Kt>f8y4-5$tBFLwhbcXt(F;Z^Tdj z!AUH+()aF#5!FGps^7nttUV0%n54sxa6o&LZThZVq~Cx}%;*`EPv)@~gk?-0*o5wh zrNua8nnP+`O`}z~3`bTZlf5zgIea1sN5b>)lj3^1lLQE@sq&*mYbXvn@?9nm^LmG> zlhV0cz^K7TBDWpa6*nYh_39gre!ynr_u6ynA%9cz=K$jc7`u^o>TR#*3tUy1T5tMZ zBfAZ!COM5xPtQ^RfTRF&IvbD4y0t_TaWM5IcskBH(YL{~9%NL0q=x;X0A*9G`QCeT z&5s#a7eKM5BpopRe9<`V>_c&u+>x#on?P&^Xuob+%c_~@UK(WNuU`(s5K?RzN0LZK znwi%910abof>bS?egHFnfQ$db-Y}Rh@oq3wP&A*fPK__LpeLZDC#1r5@&l*3Z0*-c z;TbkcS2lm*6*Y?W8|WhD1xPqaexe;sfmrm&DWLIZ&L1L0k_mRXdx3-Y7!<-kD2n32 zDZKI~BJ-Ug8^~kyo5ZoG?c`Cr3`>(Fq234O2LTF{(eh8|5a(51UXjDtu_IdKT_POp zI`3e1F@DD(#phkmr_TO0KMn~qv!d>dd zj-o)3mm4(?TpQSCn5|pM9OR@%edw zkLeHEWM`_}7%xg6JHm11VQe%a5)|jXE6wO7J<66b0@jEdrQ2^klX$iJ&-8BvqVZqn z62LqxuwM{keBqYON}^O>imD5f#zjpK1(`DPy2wRs1=Hx{Zo-XG$;6^+aMV3J|C)Qt zkOkSPh?mUuQPne4DI<&#G?f$`-#4mD2xS?!oAp+jt0&H+l#p66hIa~8WE+-|2s?jR z`w%Xs4rLTAGlU{P>qWyQchZWb^m5P99MGmEN*os&(1rBowaq7cO&v!)ip$+lC%bAz zcjUP|Cu!&7CsX!?m|^%Fck#B31Th}^i z%eUTpi3dNuX(Yy_>312tzPDS$CL0rIkrrm@QPI17Mgq||-m8xA+F*Es?(Yyp3J9gI zpSt?=zm3KR6{*mioVJQU5Q}L;N3GRJN9tq3%%pr%XmVrBucyB5nQ1F-S3ns2~A`pIILHz#k#I`?1M*KduGv_8xu*2V#+!fu`T-98cR+bcN@x7mr{Ivjg zssuc@_12#n?7b`X7`c`&K?sZjbGOu=WzMgx@L#37ivM2V1y=I+Vevg*R0fRjNpFvR z@cQO_E=HJ_@K%D+G$LQfB}cHvmIez=x;#Gie)Y01y`YQd#OM{gksC~5Rbc0vOT3z) zxyFO^MlBa9jkx&qXPZS)n7AhWMePNk)u%dEV1Fk@mr>+_WfdLdRAq$AC`Mi<`S39& zuKq2fNOWD4s;4MDOQZe8mR>Q&hJSC?5u?p5uRJ|lBsOB~B`o8*Se}gYJ%rR9aU#F5 zOFu}3@e-$5l1VnGSYlvRbM9bhJb+`*s2X(>pUOW;h19(w z%?V{YYtUYPIpk|@Q%|G_P$mpdt2f&<C0#29&X0y7*KZYh`O z8aOr)=-4QL!by6oMB);jE>8xas%u~PH;pOBCD_1^vV~obxdLY5$hw>aMIk4@>^$PE zSl1%Vv~KnaBCIS*MR2_QWUW`VrCmVpY6s0~J~Pa2g%Q!!7R$Fs@jnUAz@YeNwxmt6B z3aaW1P9LS}N+Gy^iMerWQ>~jKEl)lEU!bzG&RQ|QGl?i|5x>D4iv zVB@dM%Ra-Nj%Jf===jWl^OZX#zBYQ>`S2d_d?~7WsW=^#apwoR$d(Klz}4bvw@D_p zPAL?4NM!+i-_5HbU6CJeVvd+(SVE~!NJmR!c~z@yG?+z-EspJPs}``xYIb=9@`F~m z_abfv<1lGjx8}65*)@_hodgNBnR}H8#NWIFDyz3uhEH)43b<&15_^a*+?JrP~-8z>l?wQ00EP4;%BI_uSo0iMAzP->Ad2M{WKOl+w%EAk+)_K;e8Xzi(Y z8(e$1&T#ClgzPbZLAHQGOKCwM3?>2!@(frO1*dWz|v?x$|(2+PLe`B*!^a0xP)Hcs0yWa!>ol6hXlt zd7lF(=VL~^nB0fH(X)7Z9QRa)y6)UnaD=!9e7Zvyk((xfE1P<+>fjqs%&FuLyNq6g zeXnBvGW0Fl3U)}`HPHnr2yyI8!EwI3ALg(=bno_;j)`Z0v9C#VT}1)09AIVU!RRA_ z1Ll$FKkS(=K~(e$dU!5fz;wE+6GhOrwIXj9(@n4YSi>{RRR&tCJFDgKr-OxY>6_IT z-R#Z+XSx6ZkYEf{zjCxL?BliZN|X(Fi+`n;Lw-L2;Ni2LmCg#jAPbZTP|=^`?lebm zm{!ZOfD3h2(uzl8Rt&#kB+B&7JeQxl(uB1k4H?~skgia1g4>MHf!p-Qh2N}_*y+0z zD+{2Xh92f^i>9ClHbq$d^=?yC;zPSYNa$-~E|LeVw+FeD0b6ya;#Q((EjoS2cx-)`W-p$C{s8|LGJU0`WKH<`O{RB`o0R;#NvU3UBF4}lj+ZN!~L zBXP2aETRmlv{3luk^996L;V#jqCLbKGzGtLoRW3rJ(`x68nlP(+CtQ#ST)*7lb0F!B}E~7uO_kq4> z5970?Q*Hp~AtZ1!cPIzMMwCEl_b8npmtZW62lprZzkFTW(V#n|=X87gxmYam+dbnU z!_fhnq2YFuYzlAm4*_*BD{`dzDt;_;=(X-3cjJmKGb@u!eLfQ}9|=b)eLT34Nkf2* zq9g6~df1wFannn^(>*EhU94E-vcZrHMIH@OM<=q-s!RAzB7v2jL!J*giaf#{h=M=F zN@Jml{etoR)J7?gk0#dYjx`xUxv#`XhAu{;pMQvcPKpF8LTRoh#xVG3P=tPn9-prs z1E`sGTmID0QO#P>!(wiQV|AMLIRh*A>3TC!9_+puj&muPF6K0m`bfP0H2bw8R z9o{=)ACb?9@Tc+w-by%Y^uN~hc}<|!`$f@HyV7dIx`BDOl&3n-#rq_oC$}X9;VyZ9 z?p+yj<%q}eL8B}pI?Wo`_W*`BT8l-qP4v6GbvDD73KG0lP~3uHj@eK-I?`@Z`E>Mp zZK7N_ekru{{GP-c=H)p@4g3bRjLyZNbOd4uU9;Rgs6s3NNru;ZN?V0M!)$D}N;NG-&BlmPyvuz9!pyluCQ{;lTQ2lm*oe~nzUi<@!j{?7*4iF?m! z?Wf21>#m)^j~&)g&;Grxpz3LYG*HB&J%t#!Oak{^`zMXtc3(v5q^gh$bUS^mf5MjC zH`j{Lw_0+vbbz1xwj`4NIG4i&H9Hgap&!rxMmYJ<3uiYuEsX_+JYM5hHW9nqFRTt8 zhz%Tm4F8O>JQ*21YJlPPSB^gPrTPook9zZ9)MVJ&RU;7+*xR3`{oCx%Mr3{GVZDEA zT^Z)STVWpIekS^P@UX8FVJT=gmldZ1iP<07y+m*3`egv-&Ep;#impPSG={L+ADy~7 z%tRX>4l`ux2=r=o+32dn^zT=#N5F}ekzhjHkE5( zKf#iFDh2NVIPFBWfyvSQ&S7dT0Sif4-mb&Znk71!sr;^r210T)Rc+1XNGEaK z?MRp<#VWufA7W^}*5pcR8!pS*QP#hgx}MpCJ+`Ula`Jk6(y8~VywI*F@fQ4WgM zl80T+1@Gsc09^?~LQPF$58^`Tye#tRa{QF-rn{}V8KXk&>TmI|h*C=Bz9&98Llil2 z)U!GST1SD6M<`>^mVJ(9!+D^mZ`=rQq(+$a<-`y!Dgs#Qj`VrAq?#xm=p40WBP-K%AbA^yocNmqZ4ha z+k>13qPo<8KkRqdHHm`zUfe)jXQ#9jny2sNrL)5ULWXz?t%x`#ZKTFF$(1dCwu5{NL{w>xp z2FN_rXb~kCh!PW1kW&rRlPsGvqT`vgd1zXvr0Xy)|)0{PgbJd)olpE5NVXyb}K?g}{WiMJ?u$d;d?%%A0+x_?=bg?pgl z|E1Z14M|V;$cp-ULr1TWlh3~}gY63ZwaY!N^k8+ec#{P@UW3`X1uwx@ZhS*DAxTHr z1>YcVpK;*ruY0c`bk3YWG$e3rO#yiD^`_sn|NVi%p2^oeHT8}y^`Y*)}C^a zXT3ULgj^0B1RNIhO^iH4yoXp24svgX&@9r{Gm`EkbVF+I$|!h%c>e50JO&)myrxG% zxeipRaL``*(BRNrQk2IRW~(2l{ZaQtf@jws4mGyIo19NJ)~fEB4Q0pZZ2mWf9&+rN zGqQf9+dNBVc{ap@!&XaTHS>?HILxxW$05iri8H8cZC|PhJ9cN1tLtyLDxCiKsLDyw zhzB&&f-E+9W8MGL)tN^%afAUpZcS0ns6Yf(k+X6mNChJx^6&uVkU|9%j1VG%CL9Ws zLQJKgk4qU2l_RZ93!xR{5)U*YNCXr`TZL8vgoHCnh!-kKhb?H=>=2SiNFLH? zSUXu`-egvzT;)zlF`-PJeUkQAV$`TtCEAf#k`P~(-)&%$>*B&9B&Tdpb~Av~KgJtyx!hA1`E`ICfU?QCKkZg-2tncPAiE zu1hEhAe}6mG?NeSD|nKzZrA$6^2z53AYiz@X0xQ|d|Q?8*=dV4cZCBJ_VkVsuePbA z?|f;GRhB2B^`1wr{YtIO-^-^4vJ)DSxBWyFyGK(8Ge#C^E_GEK4AUR-*4N|8=v~4K)fe;d93>1V`Ix|d`pvCg@P2C^I0t$9i0ss?IG+crlg|A zDayU7$hwzTbl_T<)FqhM9PvC&@i3X;^UD*rciH^rsmn}4bA`J7{S;@RsFdN`6~D-e zFR^&<)lwUOg3fPVD!k}1X;nA#UcJ=sg7);52Z{N?EN=4SP1X6Czo(nu33R{y+MH5w z@_E4vO4~UW=bC(KVM6x4y0mZyI?Z>>bbZVy8qMv~0Y+&5`lYWue+$oeUeIl||djN79#HQB4{3 zFV7|CxISc^+7Wv`J^ohK`|=3?zvK&2wN1^tJ^1U5{eIin5;`j3ZQXY-$=@z7GLfI= z<|xx^6&VPPb!)w6935XTj{M21E6rIHQ@JP0c}<5CJ)7ksev_M+WPeyOw2Rtn8eExu zLB6%uG<|17yWX(><$O9%ZjqS2U(nxRnQc%We$>;6mB|aak)-bCzt+~UOmk{-VoGf| zyfVB>)$_9b>#jcc|FStSpFkbc_6wk)>dle)05u{Wptzlp?n*@uKo}3Fy1Y z945IoXJa+zo>Qk&)Ab^eC6y0~uXevqh?5@?*>vX6Sq|^ax>?7@4SGV_J`_o-)ipE+o>c7k+cvAA-xwbQCNL5>Hrukc#QcZy7C4w&eU~VUxMQBt6xTLgFN%AQ< z2&@sJwGq8q3sfq4!n?nK?xZo8k8J^RgoZ$MOdYVstdYnsLG_p&Dv&(m=|IcYb{P4& z7Al>8aoL^|z;`XS*$(-JfK{uL=fXW03#cg6lC|QBF%JA+DAd;bZ}DH7O3`{BFP6}R|~9FgEIj>t@M6v#F7C9 zR-=I5?}D^2vF^$N2gEQ2>k2iMfwqhU-l8Ps`73eR2NK{(18{$UjDAc&gENdWPr#PT z_DjT|91#(iiHy+MB${(@rWr#Usx1zj{(cVBM{$`8IB0@}K{AmU5sOv^s|Ga?_f$Bz z6|e?LC@zu|C;2W7lk6NcCt^V}Uz!#HH!>@L^XUXpMZ0Fm3{$k#NMd1x)Ox%uXNQ&zGcmeO$I?>;D%hxJbeBPfTju ieoJNygGq~ti=f4Ndk~=$oj_Ov-&!#Kmkvb;gnt24a60V( diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ffed3a25..50832291 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index af6708ff..65dcd68d 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m"' +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 0f8d5937..6689b85b 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,4 +1,20 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -9,19 +25,23 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From be50b03f12bfc5122a3f45d3231a506b6d73cb3d Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Mon, 26 Aug 2024 22:30:15 +0200 Subject: [PATCH 18/28] deps bump --- build.gradle.kts | 2 ++ jenkinsResources/core-version.txt | 2 +- test/integration/groovy/printLocationTest.groovy | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index afd047aa..a731a1da 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -54,6 +54,8 @@ dependencies { testImplementation("org.slf4j", "slf4j-simple", slf4jVersion) // integration-tests + integrationTestImplementation("org.jenkins-ci.main", "jenkins-test-harness", "2254.vcff7a_d4969e5") + integrationTestImplementation("org.spockframework", "spock-core", spockVersion) integrationTestImplementation("org.codehaus.groovy", "groovy-all", groovyVersion) diff --git a/jenkinsResources/core-version.txt b/jenkinsResources/core-version.txt index b8b8d1ea..52ee3913 100644 --- a/jenkinsResources/core-version.txt +++ b/jenkinsResources/core-version.txt @@ -1 +1 @@ -2.246 \ No newline at end of file +2.462.1 \ No newline at end of file diff --git a/test/integration/groovy/printLocationTest.groovy b/test/integration/groovy/printLocationTest.groovy index e5a3a09f..57cbdf32 100644 --- a/test/integration/groovy/printLocationTest.groovy +++ b/test/integration/groovy/printLocationTest.groovy @@ -35,7 +35,7 @@ class printLocationTest { final WorkflowJob workflowJob = rule.createProject(WorkflowJob, 'project') workflowJob.definition = flow - rule.assertLogContains('Running on node master', rule.buildAndAssertSuccess(workflowJob)) + rule.assertLogContains('Running on node built-in', rule.buildAndAssertSuccess(workflowJob)) } } From 5fb93d23435a17296f056119709ddc635609fa45 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Mon, 26 Aug 2024 22:30:59 +0200 Subject: [PATCH 19/28] Additionally check toUri --- src/ru/pulsar/jenkins/library/utils/FileUtils.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy b/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy index 8ad5f0d5..721f6800 100644 --- a/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy +++ b/src/ru/pulsar/jenkins/library/utils/FileUtils.groovy @@ -59,9 +59,9 @@ class FileUtils { private static boolean isValidUrl(String url) { try { - new URL(url) + new URL(url).toURI() return true - } catch (MalformedURLException e) { + } catch (MalformedURLException | URISyntaxException e) { return false } } From 258af0e71d53ebb109e6b00f08c4da8a44872353 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Mon, 26 Aug 2024 22:33:25 +0200 Subject: [PATCH 20/28] loadSources -> loadConfiguration --- resources/globalConfiguration.json | 2 +- resources/schema.json | 4 ++-- .../jenkins/library/configuration/TimeoutOptions.groovy | 2 +- vars/pipeline1C.groovy | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index b363d66d..0783472c 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -28,7 +28,7 @@ "bdd": 120, "getBinaries": 60, "createInfoBase": 60, - "loadSources": 60, + "loadConfiguration": 60, "designerToEdtFormatTransformation": 60, "edtToDesignerFormatTransformation": 60, "edtValidate": 240, diff --git a/resources/schema.json b/resources/schema.json index 987d88bf..3d20e6da 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -106,9 +106,9 @@ "type" : "integer", "description" : "Таймаут шага создания информационной базы, в минутах.\n По умолчанию содержит значение 60.\n " }, - "loadSources" : { + "loadConfiguration" : { "type" : "integer", - "description" : "Таймаут шага загрузки исходников в базу, в минутах.\n По умолчанию содержит значение 60.\n " + "description" : "Таймаут шага загрузки конфигурации в базу, в минутах.\n По умолчанию содержит значение 60.\n " }, "initInfoBase" : { "type" : "integer", diff --git a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy index aad73b01..37babfc9 100644 --- a/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/TimeoutOptions.groovy @@ -24,7 +24,7 @@ class TimeoutOptions implements Serializable { @JsonPropertyDescription('''Таймаут шага загрузки конфигурации в базу, в минутах. По умолчанию содержит значение 60. ''') - Integer loadSources + Integer loadConfiguration @JsonPropertyDescription('''Таймаут шага инициализации информационной базы, в минутах. По умолчанию содержит значение 60. diff --git a/vars/pipeline1C.groovy b/vars/pipeline1C.groovy index c3dab0e7..867e3830 100644 --- a/vars/pipeline1C.groovy +++ b/vars/pipeline1C.groovy @@ -99,7 +99,7 @@ void call() { stage('Загрузка конфигурации') { steps { - timeout(time: config.timeoutOptions.loadSources, unit: TimeUnit.MINUTES) { + timeout(time: config.timeoutOptions.loadConfiguration, unit: TimeUnit.MINUTES) { script { if (config.infoBaseFromFiles()) { // Создание базы загрузкой из файлов From 9c0ba58d5a706fb31d4cc49cbee2fefaf6d54c3a Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Mon, 26 Aug 2024 23:00:12 +0200 Subject: [PATCH 21/28] JDK 17 on CI --- .github/workflows/gradle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index d27ea4bb..a712106c 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v4 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 From 50e73ea800525357a94c6fe6e3753139c6e08d1b Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Tue, 27 Aug 2024 11:02:19 +0300 Subject: [PATCH 22/28] =?UTF-8?q?=D0=97=D0=BD=D0=B0=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BA?= =?UTF-8?q?=20vrunnerSettings=20"=D0=9F=D0=BE=20=D1=83=D0=BC=D0=BE=D0=BB?= =?UTF-8?q?=D1=87=D0=B0=D0=BD=D0=B8=D1=8E"=20=D1=82=D0=B5=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D1=8C=20=D1=80=D0=B0=D0=B2=D0=BD=D0=BE=20./tools/vrunner?= =?UTF-8?q?.json=20=D0=92=20=D1=81=D0=BB=D1=83=D1=87=D0=B0=D0=B5=20=D0=B5?= =?UTF-8?q?=D1=81=D0=BB=D0=B8=20=D0=B1=D0=B0=D0=B7=D0=B0=20=D0=B8=D0=BD?= =?UTF-8?q?=D0=B8=D1=86=D0=B8=D0=B0=D0=BB=D0=B8=D0=B7=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B0=20=D0=B8=D0=B7=20=D1=88=D0=B0=D0=B1?= =?UTF-8?q?=D0=BB=D0=BE=D0=BD=D0=B0=20-=20=D0=BD=D0=B0=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B9=D0=BA=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D1=8F=D1=8E=D1=82=D1=81=D1=8F.=20=D0=95=D1=81=D0=BB=D0=B8=20?= =?UTF-8?q?=D0=BD=D0=B5=D1=82=20-=20=D0=BD=D0=B5=20=D0=B4=D0=BE=D0=B1?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D1=8F=D1=8E=D1=82=D1=81=D1=8F.=20=D0=AD?= =?UTF-8?q?=D1=82=D0=BE=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82?= =?UTF-8?q?=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BD=D0=B0=20=D1=8D?= =?UTF-8?q?=D1=82=D0=B0=D0=BF=D0=B5,=20=D0=B3=D0=B4=D0=B5=20=D0=BD=D0=B0?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B8=20=D0=BD=D0=B5=20?= =?UTF-8?q?=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D1=8B.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/globalConfiguration.json | 2 +- .../configuration/InitInfoBaseOptions.groovy | 4 ++++ .../library/steps/InitFromFiles.groovy | 12 +++++----- .../library/steps/InitFromStorage.groovy | 2 +- .../jenkins/library/steps/InitInfoBase.groovy | 24 ++++++++++--------- 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/resources/globalConfiguration.json b/resources/globalConfiguration.json index 0783472c..5e4399c5 100644 --- a/resources/globalConfiguration.json +++ b/resources/globalConfiguration.json @@ -44,7 +44,7 @@ "runMigration": true, "additionalInitializationSteps": [], "templateDBPath": "", - "vrunnerSettings": "", + "vrunnerSettings": "./tools/vrunner.json", "extensions": [] }, "bdd": { diff --git a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy index 6570c079..fa947828 100644 --- a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy @@ -80,4 +80,8 @@ class InitInfoBaseOptions implements Serializable { ", extensions=" + extensions + '}' } + + boolean templateDBLoaded() { + return templateDBPath != null && !templateDBPath.isEmpty() + } } diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy index 8e9ba36f..0d8b8c58 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy @@ -9,7 +9,7 @@ import ru.pulsar.jenkins.library.utils.VRunner class InitFromFiles implements Serializable { - private final JobConfiguration config; + private final JobConfiguration config InitFromFiles(JobConfiguration config) { this.config = config @@ -28,26 +28,26 @@ class InitFromFiles implements Serializable { Logger.println("Распаковка файлов") - String srcDir; + String srcDir if (config.sourceFormat == SourceFormat.EDT) { - def env = steps.env(); + def env = steps.env() srcDir = "$env.WORKSPACE/$EdtToDesignerFormatTransformation.CONFIGURATION_DIR" steps.unstash(EdtToDesignerFormatTransformation.CONFIGURATION_ZIP_STASH) steps.unzip(srcDir, EdtToDesignerFormatTransformation.CONFIGURATION_ZIP) } else { - srcDir = config.srcDir; + srcDir = config.srcDir } Logger.println("Выполнение загрузки конфигурации из файлов") - String vrunnerPath = VRunner.getVRunnerPath(); + String vrunnerPath = VRunner.getVRunnerPath() def command = "$vrunnerPath update-dev --src $srcDir --ibconnection \"/F./build/ib\"" def options = config.initInfoBaseOptions String vrunnerSettings = options.vrunnerSettings - if (vrunnerSettings != '' && steps.fileExists(vrunnerSettings)) { + if (options.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { command += " --settings $vrunnerSettings" } diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy index fbd04c10..f944c5a9 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy @@ -60,7 +60,7 @@ class InitFromStorage implements Serializable { def options = config.initInfoBaseOptions String vrunnerSettings = options.vrunnerSettings - if (vrunnerSettings != '' && steps.fileExists(vrunnerSettings)) { + if (options.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { command += " --settings $vrunnerSettings" } diff --git a/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy b/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy index c1e36d07..92457dca 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy @@ -9,7 +9,7 @@ import ru.pulsar.jenkins.library.utils.VRunner class InitInfoBase implements Serializable { - private final JobConfiguration config; + private final JobConfiguration config InitInfoBase(JobConfiguration config) { this.config = config @@ -30,7 +30,15 @@ class InitInfoBase implements Serializable { List logosConfig = ["LOGOS_CONFIG=$config.logosConfig"] steps.withEnv(logosConfig) { - String vrunnerPath = VRunner.getVRunnerPath(); + String vrunnerPath = VRunner.getVRunnerPath() + + // Нужны ли настройки vrunner + def options = config.initInfoBaseOptions + String settingsIncrement = '' + String vrunnerSettings = options.vrunnerSettings + if (options.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { + settingsIncrement = " --settings $vrunnerSettings" + } if (config.initInfoBaseOptions.runMigration) { Logger.println("Запуск миграции ИБ") @@ -40,16 +48,10 @@ class InitInfoBase implements Serializable { if (steps.isUnix()) { executeParameter = '\\' + executeParameter } - command += executeParameter; + command += executeParameter command += ' --ibconnection "/F./build/ib"' - def options = config.initInfoBaseOptions - - String vrunnerSettings = options.vrunnerSettings - if (vrunnerSettings != '' && steps.fileExists(vrunnerSettings)) { - command += " --settings $vrunnerSettings" - } - + command += settingsIncrement // Запуск миграции steps.catchError { VRunner.exec(command) @@ -69,7 +71,7 @@ class InitInfoBase implements Serializable { } else { config.initInfoBaseOptions.additionalInitializationSteps.each { Logger.println("Первичная инициализация командой ${it}") - VRunner.exec("$vrunnerPath ${it} --ibconnection \"/F./build/ib\"") + VRunner.exec("$vrunnerPath ${it} --ibconnection \"/F./build/ib\"${settingsIncrement}") } } } From f158b482e480660e40cb91d0671b8fc045ea47b2 Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Tue, 27 Aug 2024 11:27:36 +0300 Subject: [PATCH 23/28] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=20=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=B1=D0=BA=D0=B8=20=D1=81=20=D0=B7=D0=B0=D0=B3=D1=80?= =?UTF-8?q?=D1=83=D0=B7=D0=BA=D0=BE=D0=B9=20=D1=80=D0=B0=D1=81=D1=88=D0=B8?= =?UTF-8?q?=D1=80=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pulsar/jenkins/library/steps/LoadExtensions.groovy | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy index 425b6682..f757f426 100644 --- a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy @@ -88,6 +88,15 @@ class LoadExtensions implements Serializable { def optionsInstance = config."$optionsName" if (optionsInstance) { + try { + // Для InitInfoBaseOptions необходимо возвращать путь к файлу настроек vrunner только если база загружается из архива + if (!optionsInstance.templateDBLoaded()) { + return "" + } + } catch (MissingMethodException e) { + // Метод templateDBLoaded вполне может отсутствовать, и это не является ошибкой + } + return optionsInstance."vrunnerSettings" } else { return "" From a9fbf868c97a7cd5fbf3d960f3a591715702c857 Mon Sep 17 00:00:00 2001 From: Egor Ivanov Date: Wed, 28 Aug 2024 21:07:32 +0300 Subject: [PATCH 24/28] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=B2=20=D1=81=D1=85=D0=B5=D0=BC=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/schema.json | 6 +++--- .../library/configuration/InitInfoBaseOptions.groovy | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/resources/schema.json b/resources/schema.json index 3d20e6da..f1428bb3 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -179,11 +179,11 @@ }, "vrunnerSettings" : { "type" : "string", - "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию не заполнено, требуется, если на этапе подготовки база загружается из архива.\n " + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\"\n Требуется, если на этапе подготовки база загружается из эталона. \n " }, - "templateDBPath": { + "templateDBPath" : { "type" : "string", - "description" : "Путь к конфигурационному файлу эталонной базы данных.\n * По умолчанию не заполнен.\n * Указывается путь к файлу *.dt или *.1CD\n " + "description" : "\n Путь к файлу эталонной базы данных.\n * По умолчанию не заполнен;\n * Указывается путь к файлу *.dt или *.1CD.\n " }, "extensions" : { "type" : "array", diff --git a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy index fa947828..7f99f6df 100644 --- a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy @@ -26,12 +26,13 @@ class InitInfoBaseOptions implements Serializable { String[] additionalInitializationSteps @JsonPropertyDescription("""Путь к конфигурационному файлу vanessa-runner. - По умолчанию не заполнено, требуется, если на этапе подготовки база загружается из архива. + По умолчанию содержит значение "./tools/vrunner.json" + Требуется, если на этапе подготовки база загружается из эталона. """) String vrunnerSettings @JsonPropertyDescription(""" - Путь к конфигурационному файлу эталонной базы данных. + Путь к файлу эталонной базы данных. * По умолчанию не заполнен; * Указывается путь к файлу *.dt или *.1CD. """) From 5c5b2842b2d9ae179a642b322785ae07ad275870 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 29 Aug 2024 23:00:31 +0200 Subject: [PATCH 25/28] =?UTF-8?q?=D0=9D=D0=B5=D0=B1=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D1=88=D0=BE=D0=B9=20=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +++ .../library/steps/LoadExtensions.groovy | 25 ++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..7b016a89 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "java.compile.nullAnalysis.mode": "automatic" +} \ No newline at end of file diff --git a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy index f757f426..9caf9296 100644 --- a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy @@ -83,23 +83,18 @@ class LoadExtensions implements Serializable { return "" } - String optionsName = "${stageName}Options" - - def optionsInstance = config."$optionsName" - - if (optionsInstance) { - try { - // Для InitInfoBaseOptions необходимо возвращать путь к файлу настроек vrunner только если база загружается из архива - if (!optionsInstance.templateDBLoaded()) { - return "" - } - } catch (MissingMethodException e) { - // Метод templateDBLoaded вполне может отсутствовать, и это не является ошибкой - } + String optionsPropertyName = "${stageName}Options" + def optionsInstance = config."$optionsPropertyName" - return optionsInstance."vrunnerSettings" - } else { + if (!optionsInstance) { return "" } + + // For InitInfoBaseOptions, return the vrunner settings path only if the database is loaded from an archive + if (optionsInstance instanceof InitInfoBaseOptions && !optionsInstance.templateDBLoaded()) { + return "" + } + + return optionsInstance."vrunnerSettings" } } From a656789870edec7786ceac85a43ea67114ed6691 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 29 Aug 2024 23:07:14 +0200 Subject: [PATCH 26/28] =?UTF-8?q?=D0=92=D1=8B=D0=BD=D0=BE=D1=81=20template?= =?UTF-8?q?DBLoaded=20=D0=BD=D0=B0=20=D1=83=D1=80=D0=BE=D0=B2=D0=B5=D0=BD?= =?UTF-8?q?=D1=8C=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../library/configuration/InitInfoBaseOptions.groovy | 4 ---- .../jenkins/library/configuration/JobConfiguration.groovy | 4 ++++ src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy | 2 +- .../pulsar/jenkins/library/steps/InitFromStorage.groovy | 2 +- src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy | 8 ++++---- src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy index 7f99f6df..3ad72b92 100644 --- a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy @@ -81,8 +81,4 @@ class InitInfoBaseOptions implements Serializable { ", extensions=" + extensions + '}' } - - boolean templateDBLoaded() { - return templateDBPath != null && !templateDBPath.isEmpty() - } } diff --git a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy index 080bc23a..8330abe6 100644 --- a/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/JobConfiguration.groovy @@ -115,6 +115,10 @@ class JobConfiguration implements Serializable { } } + boolean templateDBLoaded() { + return initInfoBaseOptions.templateDBPath != null && !initInfoBaseOptions.templateDBPath.isEmpty() + } + String v8AgentLabel() { return v8version } diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy index 0d8b8c58..47445ce3 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromFiles.groovy @@ -47,7 +47,7 @@ class InitFromFiles implements Serializable { def options = config.initInfoBaseOptions String vrunnerSettings = options.vrunnerSettings - if (options.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { + if (config.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { command += " --settings $vrunnerSettings" } diff --git a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy index f944c5a9..79b805db 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitFromStorage.groovy @@ -60,7 +60,7 @@ class InitFromStorage implements Serializable { def options = config.initInfoBaseOptions String vrunnerSettings = options.vrunnerSettings - if (options.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { + if (config.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { command += " --settings $vrunnerSettings" } diff --git a/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy b/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy index 92457dca..d3cedc6b 100644 --- a/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy +++ b/src/ru/pulsar/jenkins/library/steps/InitInfoBase.groovy @@ -36,11 +36,11 @@ class InitInfoBase implements Serializable { def options = config.initInfoBaseOptions String settingsIncrement = '' String vrunnerSettings = options.vrunnerSettings - if (options.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { + if (config.templateDBLoaded() && steps.fileExists(vrunnerSettings)) { settingsIncrement = " --settings $vrunnerSettings" } - if (config.initInfoBaseOptions.runMigration) { + if (options.runMigration) { Logger.println("Запуск миграции ИБ") String command = vrunnerPath + ' run --command "ЗапуститьОбновлениеИнформационнойБазы;ЗавершитьРаботуСистемы;" --execute ' @@ -61,7 +61,7 @@ class InitInfoBase implements Serializable { } steps.catchError { - if (config.initInfoBaseOptions.additionalInitializationSteps.length == 0) { + if (options.additionalInitializationSteps.length == 0) { FileWrapper[] files = steps.findFiles("tools/vrunner.init*.json") files = files.sort new OrderBy( { it.name }) files.each { @@ -69,7 +69,7 @@ class InitInfoBase implements Serializable { VRunner.exec("$vrunnerPath vanessa --settings ${it.path} --ibconnection \"/F./build/ib\"") } } else { - config.initInfoBaseOptions.additionalInitializationSteps.each { + options.additionalInitializationSteps.each { Logger.println("Первичная инициализация командой ${it}") VRunner.exec("$vrunnerPath ${it} --ibconnection \"/F./build/ib\"${settingsIncrement}") } diff --git a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy index 9caf9296..da3e2169 100644 --- a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy @@ -91,10 +91,10 @@ class LoadExtensions implements Serializable { } // For InitInfoBaseOptions, return the vrunner settings path only if the database is loaded from an archive - if (optionsInstance instanceof InitInfoBaseOptions && !optionsInstance.templateDBLoaded()) { + if (optionsInstance instanceof InitInfoBaseOptions && !config.templateDBLoaded()) { return "" } - return optionsInstance."vrunnerSettings" + return optionsInstance.vrunnerSettings } } From 63b2800b0680a9856bc44cd03a82817ec55adec5 Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 29 Aug 2024 23:15:20 +0200 Subject: [PATCH 27/28] =?UTF-8?q?=D0=9D=D0=B5=D0=B1=D0=BE=D0=BB=D1=8C?= =?UTF-8?q?=D1=88=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++-- resources/schema.json | 2 +- .../library/configuration/InitInfoBaseOptions.groovy | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 52a23d08..3018524c 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ pipeline1C() "name": "ИмяРасширения1", "initMethod": "fromSource", "path": "путь/до/исходников/расширения", - "stages": ['bdd', 'yaxunit'] + "stages": ["bdd", "yaxunit"] }, { "name": "ИмяРасширения2", @@ -217,9 +217,10 @@ pipeline1C() "templateDBPath": "путь/до/файла/базы.dt" } ``` + * Поддерживается загрузка файлов формата `.dt` и `.1CD`. * Путь к файлу базы может быть как локальным, так и удаленным (URL). -* Если эталонная база содержит пользователей, то необходимо указать файл конфигурации, который будет использован для дальнейшей инициализации базы данных. Для этого необходимо указать параметр `initInfobase` -> `vrunnerSettings`: +* После загрузки базы для инициализации будет использоваться файл настроек `vanessa-runner` (включая логин и пароль от ИБ), указанный в параметре `initInfobase` -> `vrunnerSettings`. По умолчанию используется файл `tools/vrunner.json`. ```json "initInfobase": { @@ -227,6 +228,7 @@ pipeline1C() "vrunnerSettings": "tools/vrunner.json" } ``` + ## Настройка шага YAXUnit * Добавить расширение `YAXUnit` и дополнительные расширения с тестами можно в `jobConfiguration.json` -> `initInfobase` -> `extensions`. Они будут загружены при инициализации ИБ. diff --git a/resources/schema.json b/resources/schema.json index f1428bb3..58561f05 100644 --- a/resources/schema.json +++ b/resources/schema.json @@ -179,7 +179,7 @@ }, "vrunnerSettings" : { "type" : "string", - "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\"\n Требуется, если на этапе подготовки база загружается из эталона. \n " + "description" : "Путь к конфигурационному файлу vanessa-runner.\n По умолчанию содержит значение \"./tools/vrunner.json\"\n Используется, если на этапе подготовки база загружается из эталона. \n " }, "templateDBPath" : { "type" : "string", diff --git a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy index 3ad72b92..46ba640e 100644 --- a/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy +++ b/src/ru/pulsar/jenkins/library/configuration/InitInfoBaseOptions.groovy @@ -27,7 +27,7 @@ class InitInfoBaseOptions implements Serializable { @JsonPropertyDescription("""Путь к конфигурационному файлу vanessa-runner. По умолчанию содержит значение "./tools/vrunner.json" - Требуется, если на этапе подготовки база загружается из эталона. + Используется, если на этапе подготовки база загружается из эталона. """) String vrunnerSettings From 7f9bf6b67e9d40aabf1c93f7f12880996bab984a Mon Sep 17 00:00:00 2001 From: Nikita Fedkin Date: Thu, 29 Aug 2024 23:17:58 +0200 Subject: [PATCH 28/28] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=B8=D0=BB=D1=8F=D1=86=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy index da3e2169..1f7bef3d 100644 --- a/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy +++ b/src/ru/pulsar/jenkins/library/steps/LoadExtensions.groovy @@ -2,6 +2,7 @@ package ru.pulsar.jenkins.library.steps import ru.pulsar.jenkins.library.IStepExecutor import ru.pulsar.jenkins.library.configuration.JobConfiguration +import ru.pulsar.jenkins.library.configuration.InitInfoBaseOptions import ru.pulsar.jenkins.library.configuration.InitInfoBaseOptions.Extension import ru.pulsar.jenkins.library.ioc.ContextRegistry import ru.pulsar.jenkins.library.utils.Logger